Created
January 6, 2012 18:07
-
-
Save tremby/1571696 to your computer and use it in GitHub Desktop.
plot -- ascii plot of numerical input data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
def usage(stdout = false) | |
stream = stdout ? $stdout : $stderr | |
bin = File.basename($0) | |
indent = " " * (bin.length() + "Usage: ".length()) | |
stream.puts("Usage: #{bin} [--help|-h]") | |
stream.puts(indent + " [--vertical]") | |
stream.puts(indent + " [--width <columns>]") | |
stream.puts(indent + " [--height <rows>]") | |
stream.puts(indent + " [--label]") | |
stream.puts <<eof | |
Plot data to a bar graph on the console. | |
Use the --vertical switch to plot vertical bars rather than horizontal ones. Use | |
the --height option to specify a height when in vertical mode (defaults to the | |
height of your terminal). | |
Use the --width option to specify a width (defaults to $COLUMNS). | |
Use the --label switch to enable labelling the bars in horizontal mode. | |
Standard input should be numeric data, one number per line. | |
eof | |
end | |
# duplicate stdin so we can get the terminal size without it getting our stdin | |
# and so throwing errors | |
stdin = STDIN.dup | |
STDIN.reopen(STDOUT) | |
# get terminal size | |
terminalsize = %x(stty size).scan(/\d+/).map { |s| s.to_i } | |
# put it back how it was | |
STDIN.reopen(stdin) | |
# set defaults | |
nomoreoptions = false | |
direction = :horizontal | |
label = false | |
width = terminalsize[1] | |
if (width.nil?) | |
width = 80 | |
end | |
height = terminalsize[0] | |
if (height.nil?) | |
height = 24 | |
end | |
# handle arguments | |
while ($*.length() > 0) | |
arg = $*.shift() | |
if (arg == "--") | |
nomoreoptions = true | |
next | |
end | |
if (!nomoreoptions && arg[0,1] == "-") | |
if (arg == "--help" || arg == "-h") | |
usage(true) | |
exit(0) | |
elsif (arg == "--vertical") | |
direction = :vertical | |
next | |
elsif (arg == "--label") | |
label = true | |
next | |
elsif (arg == "--height") | |
arg = $*.shift() | |
if (arg.nil?) | |
$stderr.puts("Expected a positive integer after the --height option") | |
else | |
arg = arg.to_i() | |
if (arg > 0) | |
height = arg | |
next | |
else | |
$stderr.puts("Expected a positive integer after the --height option") | |
end | |
end | |
elsif (arg == "--width") | |
arg = $*.shift() | |
if (arg.nil?) | |
$stderr.puts("Expected a positive integer after the --width option") | |
else | |
arg = arg.to_i() | |
if (arg > 0) | |
width = arg | |
next | |
else | |
$stderr.puts("Expected a positive integer after the --width option") | |
end | |
end | |
else | |
$stderr.puts("Unknown option \"#{arg}\"") | |
end | |
else | |
$stderr.puts("Unexpected argument \"#{arg}\"") | |
end | |
# problem with arguments | |
usage() | |
exit(1) | |
end | |
# read stdin, treat each line as a float | |
data = $stdin.readlines() | |
data.map! { |datum| datum.to_f } | |
max = data.max() | |
if (direction == :horizontal) | |
if (label) | |
# get the longest string number when written as decimal | |
stringnumbers = data.map { |datum| datum.to_s().length() } | |
longestnumber = stringnumbers.max() | |
usablewidth = width - longestnumber - 1 | |
else | |
usablewidth = width | |
end | |
data.each do |datum| | |
if (label) | |
puts(datum.to_s().rjust(longestnumber) << " " << ("#" * (usablewidth * datum / max).round())) | |
else | |
puts("#" * (usablewidth * datum / max).round()) | |
end | |
end | |
else | |
# leave a row for the new prompt | |
height -= 1 | |
# get the heights of each column | |
bars = [] | |
for i in 0...width | |
bars[i] = (height * data[(i * data.length() / width).round()] / max).round() | |
end | |
for i in 0...height | |
for j in 0...width | |
if (height - i > bars[j]) | |
$stdout.write(" ") | |
else | |
$stdout.write("#") | |
end | |
end | |
$stdout.write($/) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment