15. User Interfaces

Parsing Program Arguments

# This test program demonstrates parsing program arguments.
# It uses the optparse library, which is included with ruby 1.8
# It handles classic unix style and gnu style options
require 'optparse'

@debugmode = false
@verbose = false

ARGV.options do |opts|
    opts.banner = "Usage: ruby #{$0} [OPTIONS] INPUTFILES"

    opts.on("-h", "--help", "show this message") {
        puts opts
        exit
    }
    # The OptionParser#on method is called with a specification of short
    # options, of long options, a data type spezification and user help
    # messages for this option.
    # The method analyses the given parameter and decides what it is,
    # so you can leave out the long option if you don't need it
    opts.on("-v", "--[no-]verbose=[FLAG]", TrueClass, "run verbosly") {
        |@verbose|   # sets @verbose to true or false
    }
    opts.on("-D", "--DEBUG", TrueClass, "turns on debug mode" ){
        |@debugmode|   # sets @debugmode to true
    }
    opts.on("-c", "--count=NUMBER", Integer, "how many times we do it" ){
        |@count|      # sets @count to given integer
    }
    opts.on("-o", "--output=FILE", String, "file to write output to"){
        |@outputfile|   # sets @outputfile to given string
    }
    opts.parse!
end

# example to use the options in the main program
puts "Verbose is on" if @verbose
puts "Debugmode is on" if @debugmode
puts "Outfile is #{@outputfile}" if defined? @outputfile
puts "Count is #{@count}" if defined? @count
ARGV.each { |param|
    puts "Got parameter #{param}"
}

Testing Whether a Program Is Running Interactively

Clearing the Screen

Determining Terminal or Window Size

buf = "\0" * 8
$stdout.ioctl(0x5413, buf)
ws_row, ws_col, ws_xpixel, ws_ypixel = buf.unpack("S4")

raise "You must have at least 20 characters" unless ws_col >= 20
max = 0
values = (1..5).collect { rand(20) }  # generate an array[5] of rand values
for i in values
    max = i if max < i
end
ratio = Float(ws_col-12)/max          # chars per unit
for i in values
    printf "%8.1f %s\n", i, "*" * (ratio*i)
end

# gives, for example:
#   15.0 *******************************
#   10.0 *********************
#    5.0 **********
#   14.0 *****************************
#   18.0 **************************************

Changing Text Color

# Ruby's standard distribution doesn't have an ANSI color module, but we can use
# Term::ANSIColor (http://term-ansicolor.rubyforge.org/) instead.
#-----------------------------
require 'term/ansicolor'
include Term::ANSIColor

# Text can be colored using constants
print red, "Danger Will Robinson!", reset, "\n"
print "This is just normal text\n"
print blink, "Do you hurt yet?", reset, "\n"
#-----------------------------
# Or by using functions. Functions automatically reset colors at the end.
print red("Danger Will Ronbinson!"), "\n"
print red( on_black( "venom lack" )), "\n"
print red( on_yellow( "kill that fellow" )), "\n"
print green( on_cyan( blink( "garish!" ))), "\n"
#-----------------------------
# Or by using block forms. Block forms automatically reset colors at the end.
print red { "Danger Will Robinson!" }, "\n"
print red { on_black { "venom lack" } }, "\n"
print red { on_yellow { "kill that fellow" } }, "\n"
#-----------------------------
# Or by using a String Mixin
class String
    include Term::ANSIColor
end

print "Danger Will Robinson!".red, "\n"
print "venom lack".red.on_black, "\n"
print "kill that fellow".red.on_yellow, "\n"

#-----------------------------
# To color text without using a third party library, constants can be created
# manually using ANSI escape codes. (A complete list of all codes can be found
# at http://en.wikipedia.org/wiki/Ansi_escape_codes)
# Note that \e means \033 (The escape character)
#-----------------------------
# Foreground constants
BLACK = "\e[30m"
RED = "\e[31m"
GREEN = "\e[32m"
WHITE = "\e[37m"

# Background constants
ON_BLACK = "\e[40m"
ON_WHITE = "\e[47m"
ON_YELLOW = "\e[43m"
ON_CYAN = "\e[46m"

# Style constants
BLINK = "\e[5m"
NOBLINK = "\e[25m"
BOLD = "\e[1m"
NOBOLD = "\e[22m"

RESET = "\e[0m"
#-----------------------------
puts "#{RED}Danger Will Ronbinson!#{RESET}"
puts "This is just normal text."
puts "#{BLINK}Do you hurt yet?#{NOBLINK}"
#-----------------------------
puts "#{RED}Danger Will Ronbinson!#{RESET}"
puts "#{RED}#{ON_BLACK}venom lack"
puts "#{RED}#{ON_YELLOW}kill that fellow"
puts "#{GREEN}#{ON_CYAN}#{BLINK}garish!"
#-----------------------------
print BLACK, ON_WHITE, "black on white\n"
print WHITE, ON_BLACK, "white on black\n"
print GREEN, ON_CYAN, BLINK, "garish!\n"

print RESET
#-----------------------------

Reading from the Keyboard

Ringing the Terminal Bell

Using POSIX termios

Checking for Waiting Input

Reading Passwords

Editing Input

Managing the Screen

Controlling Another Program with Expect

Creating Menus with Tk

Creating Dialog Boxes with Tk

Responding to Tk Resize Events

Removing the DOS Shell Window with Windows Perl/Tk

Program: Small termcap program

Program: tkshufflepod