Years ago I created a simple Python script to plot a list of numbers in a simple ASCII line graph. I use this script all the time; I extract (with awk,perl,pyliner,...) a column of numbers out of a log file and pipe it in to this script. Very useful since even to today most admin work is done in a character based terminal.
UPDATE (4/28/2011): Also check my other terminal console escript entries: runavg.escript, escript to beam
All numbers are rounded to an integer. It auto resizes new graph entries when a new max is set (default max is 0), and plots a new max line in bold. If you set a threshold, it outputs any line over that threshold in red. Or both.
I created an Erlang escript version of it, just as an exercise. It requires 'tput' to be in the path, this even works with the cygwin version. It also uses An Erlang version of getopt. I didn't bother to install it, I just copied getopt.erl to my src dir and compiled it. Also
chmod u+x
tgraph.escriptIt's called as part of a pipe:
$ cat test.txt | ./tgraph.escript -t 40 -c 40
or with the file as a parameter:
./tgraph.escript test.txt -t 40 -c 40
test.txt:
1
50
20
3
45
34.0
12
0
1000
0
100
34
Output:
****************************************1
****************************************50
****************20
**3
************************************45
***************************34
**********12
0
****************************************1000
0
****100
*34
tgraph.escript:
#!/usr/bin/env escript %% -*- erlang -*- %%! -smp disable %% Author: Drew Gulino -module(tgraph). -export([main/1]). main(CmdLine) -> OptSpecList = option_spec_list(), case getopt:parse(OptSpecList, CmdLine) of {ok, {Options, NonOptArgs}} -> true; {error, {Reason, Data}} -> Options = [], NonOptArgs = [], io:format("Error: ~s ~p~n~n", [Reason, Data]), version(), getopt:usage(OptSpecList, "tgraph") end, Symbol = get_opt_value(symbol,Options), Columns = get_opt_value(columns,Options), Display_number = get_opt_value(display_number,Options), Threshold = get_opt_value(threshold,Options), Maximum = get_opt_value(maximum,Options),
Bold = strip_newlines(os:cmd("tput bold")), Init = strip_newlines(os:cmd("tput init")), Dim = strip_newlines(os:cmd("tput sgr0")), Red = strip_newlines(os:cmd("tput setaf 1")), %Green = strip_newlines(os:cmd("tput setaf 2")), %Yellow = strip_newlines(os:cmd("tput setaf 3")), %Blue = strip_newlines(os:cmd("tput setaf 4")), %Magenta = strip_newlines(os:cmd("tput setaf 5")), case NonOptArgs of [] -> F = standard_io; _ -> {ok, F} = file:open(NonOptArgs, read) end, proc_file(F, {Symbol, Columns, Display_number, Threshold, Maximum} , {Bold, Init, Dim, Red}). version() -> io:format("Version: 1.1\n"). get_opt_value(Key, Options) -> case lists:keyfind(Key,1,Options) of {Key, Value} -> Value end, Value. option_spec_list() -> %CurrentUser = os:getenv("USER"), [ %% {Name, ShortOpt, LongOpt, ArgSpec, HelpMsg} {help, $h, "help", undefined, "Show the program options"}, {version, $v, "version", undefined, "Version"}, {display_number, $n, "display_number", {boolean, true}, "Display number w/graph"}, {columns, $c, "columns", {integer, 72}, "Display columns (default = 72)"}, {symbol, $s, "symbol", {string, "*"}, "Symbol to display (default = '*')"}, {threshold, $t, "threshold", {integer, 0}, "Will color lines over this value"}, {maximum, $m, "maximum", {integer, 0}, "Presets the scale for this maximum value (default = 0)"} ]. proc_file(F, Options, Tput) ->
{Symbol, Columns, Display_number, Threshold, Maximum} = Options,
{Bold, Init, Dim, Red} = Tput,
%Columns = erlang:list_to_integer(os:cmd("tput cols")) - 8},
L = io:get_line(F, ''), case L of eof -> ok; "\n" -> false; Line -> Stripped = strip_newlines(Line), Num = cast_to_integer(Stripped), io:put_chars(Init), case Num > 0 of true -> case Num >= Maximum of true -> NewMax = Num, io:put_chars(Bold); false -> NewMax = Maximum, io:put_chars(Dim) end, Scale = Columns / NewMax, Graph = lists:map(fun(_) -> io_lib:format(Symbol,[]) end , lists:seq(1,erlang:round(Num * Scale))), case Threshold of 0 -> false; _ -> case Num >= Threshold of true -> io:put_chars(Red); false -> %io:put_chars(Init) false end end, case Display_number of true -> io:format("~s~p~n",[Graph,Num]); false -> io:format("~p~n",[Graph]) end, NewOptions = {Symbol, Columns, Display_number, Threshold, NewMax}, proc_file(F,NewOptions, Tput); false -> io:put_chars(Dim), io:put_chars(Init), io:format("~p~n",[Num]), proc_file(F,Options, Tput) end end. strip_newlines(String) -> string:strip(re:replace(String,"(.*)[\n\r]","\\1", [global,{return,list}])). cast_to_integer([]) -> []; cast_to_integer(Input) when is_integer(Input) -> Input; cast_to_integer(Input) when is_float(Input) -> erlang:round(Input); cast_to_integer(Input) when is_list(Input)-> case lists:member($., Input) of true -> erlang:round(erlang:list_to_float(Input)); false -> erlang:list_to_integer(Input) end.
UPDATE (4/26/2001):
Here's a link to the original python script: tgraph.py
UPDATE (4/27/2011):
Version 1.1:
1) Fixed bug where lines were never dimmed after being bolded in cygwin
2) Changed the compiler flags to disable smp and not register the process name. Both not needed. One note: Couldn't get +Bc to work in Windows. This should change the break key to Ctrl-C, but still stays Ctrl-Break.
3) Moved tput initialization out of working loop, now runs quickly.
No comments:
Post a Comment