preload
Apr 28

From my bag of tricks…

On occasion, I run into the need to present some kind of table information on to a console/terminal session so that the information is readable. After doing this several times, I decided to write a text table class so that i didn’t have to worry about formatting the table within my code. I just set the table up with column titles and column widths and just focus on the data.

Here’s the code:

#
#  texttable.rb  --  testing tool to output a nicely formatted table.
#
# John Allen, June 2005
#  June 2010 -- Added support for word wrap fields
#

class TextTable
  #
  # tableinfo = Hash.new {
  #    "name" =>  Array(:string),
  #    "width" => Array(:fixnum),
  #    ["linebetweenrows" => Boolean,]
  #    ["hdrlinechar" => "=",]
  #    ["rowlinechar" => "-",]
  #    ["wordwrap" => Boolean]
  # }

  attr_accessor  :names,  :widths, :hdr_print_flg, :lbr_flg, :hdrchar, :linechar, :wordwrap

  @hdr_print_flg = false
  @ldr_flg = false
  @wordwrap = false

  def initialize(tableinfo)
    @names = tableinfo["name"]
    @widths = tableinfo["width"]
    if tableinfo["linebetweenrows"]
      @lbr_flg = true
    end
    if tableinfo["wordwrap"]
      @wordwrap = true
    end
    @hdrchar = tableinfo["hdrlinechar"] || "="
    @linechar = tableinfo["rowlinechar"] || "-"
  end

  def printrow(a)
    # a = Array
    buf = ""
    if not @hdr_print_flg
      buf << printHdr()
    end
    buf << "|"
    extra = []
    a.each_with_index do |n,i|
      if n.length > @widths[i]        ## check to see if value is bigger than field; chop if so
        b = n.slice(0..(@widths[i] -1))
        extra[i] = n.slice(@widths[i]..-1)
      else
        b = n
      end
      buf << " #{b}#{" "*(@widths[i] - b.length)}|"
    end
    buf << "\n"
    if @wordwrap and not extra.empty?   ## Word Wrap
      eflg = true
      while eflg          ## While stuff to word wrap
        eflg = false
        buf << "|"
        extra.each_with_index do |n,i|
          if not n.nil?
            if n.length > @widths[i]        ## check to see if value is bigger than field; chop if so
              b = n.slice(0..(@widths[i] -1))
              extra[i] = n.slice(@widths[i]..-1)
              eflg = true           ## still more to word wrap!!
            else
              b = n
              extra[i] = nil
            end
            buf << " #{b}#{" "*(@widths[i] - b.length)}|"
          else
            buf << " #{" "*@widths[i]}|"  ## add blank space for non-wordwrap field
          end
        end
        buf << "\n"
      end
    end
    buf << _line(@linechar)  if @lbr_flg
    return buf
  end

  def printHdr
    buf = _line(@hdrchar)
    buf << "|"
    @names.each_with_index do |n,i|
      buf << " #{n}#{" "*(@widths[i] - n.length)}|"
    end
    buf << "\n"
    buf << _line(@hdrchar)
    @hdr_print_flg = true
    return buf
  end

  def printLine
    buf = _line(@linechar)
    return buf
  end

  #-------------------------------------------------------------------------------------------------------#
  private
  #-------------------------------------------------------------------------------------------------------#

  def _line(char)
    b = "+"
    @names.each_with_index do |n,i|
      b << char*@widths[i]
      b << "#{char}+"
    end
    b << "\n"
    return b
  end

end

if __FILE__ == $0
  tt = {
     "name" => ["First","Last","City","State"],
     "width" => [15,15,15,6],
     "linebetweenrows" => false
  }

  names = [
      ["John","Allen","Redmond","WA"],
      ["Herman","Gonzales","Mill Creek","WA"],
      ["Jimmy","Doogle","Bothell","WA"],
      ["Jane","Goodman","Seattle","WA"]
  ]

  table = TextTable.new(tt)

  buf = ""
  names.each do |name|
    buf << table.printrow(name)
  end
  buf << table.printLine
  puts buf

end

Running the example code at the bottom prints out the following result:

C:\Server4\Dev\Ruby\exo>ruby texttable.rb
+================+================+================+=======+
| First          | Last           | City           | State |
+================+================+================+=======+
| John           | Allen          | Redmond        | WA    |
| Herman         | Gonzales       | Mill Creek     | WA    |
| Jimmy          | Doogle         | Bothell        | WA    |
| Jane           | Goodman        | Seattle        | WA    |
+----------------+----------------+----------------+-------+

the printrow() method takes an array of String values to print out. You can have a line printed out between each row if you set the linebetweenrows hash value to ‘true’ (it defaults to ‘false’). There is not a lot of error checking (as in, you can crash the program if you feed the printrow() method an array that is shorter than the number of columns), but since I mainly use it for testing or utilities, I didn’t put a lot in. Its a very handy tool to have around.

Update: I added support for word wrap in all fields recently, so I have updated the code above with that version.

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Apr 21

One of my common Python tools: use this to list out all the directories from the specified root on down, ignoring some common directories that are specified in the program. You might want to modify this code to read in your ignore list. The program will also optionally take a size limit so that it only lists directories where the storage usage is over that limit.
Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Apr 14

Let the fun begin….

Microsoft has released the first official version of its Ruby integration with .NET called IronRuby 1.0. If you look closely to the release notes, you will see me on the list of bug reporters :) As I get more familiar with it, and feel I have something worth while to post, I’ll be blogging about it too.

You can download it from the IronRuby Download page.

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Apr 13

This is a follow-on to my Python Connectivity Check Script that I posted a while back. It functions the same way…its just written in Perl. I use both program as part of a System Connectivity Check program I wrote in Ruby to connect to many hosts, upload one of these connectivity check programs, run it and place the results into an Excel spreadsheet with a simple red/green status. When you are installing systems with hundreds of nodes that all need to talk to 30-odd other nodes, its a huge time saver!

Here’s the code: Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Apr 07

Every once and a while I get too fancy for my own good. :) A customer of mine has lots and lots (well…hundreds really) of Unix hosts that need updates of config files and such. There are lots of tools out there that can do what I need to do, but they all require an install on the nodes themselves. My customer does not want any extra software on these nodes, so to do any kind of automation requires me to upload the program, run it remotely, then remove it. I have a large number of tools to do all that several different ways.

Recently though, I needed to download a large file from each node while running another program on the node at the same time. Normally I would use SCP for the download part, but for reasons that would take too long to explain, that option was not open to me. So for some reason, I was struck with the ideal to just use a custom XMLRPC client/server to do the job. Turns out the code is pretty simple. My customer only has Python on these nodes, so my XMLRPC client is written in Python:

#
# xmlxfer.py
#
import xmlrpclib
import sys
import platform

port = 80    # Some port that passes through your firewall:  80, 21, 23, 25, etc.

farfname = sys.argv[1]
localfilename = sys.argv[2]
server = sys.argv[3]
#host = platform.uname()[1]
host = platform.node()
farname = host + "-" + farfname

ff = open(localfilename, "r").read()

svr = "http://" + server + ":" + port + "/RPC2"
xmlprxy = xmlrpclib.ServerProxy(svr)

print xmlprxy.xfer(farname, ff)

Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with:
Apr 06

While there are plenty of places on the web that talk about Ruby Arrays and Ruby Classes, I never have found one that just explained how to use a Class as an Array. So I thought I would post one for those who might want something simple to reference :)

First, the sample code:

class Test
  @dd = Array.new
  def initialize
    @dd = loadArray()
  end

  def [](a)
    @dd[a]
  end

  def []=(a, b)
    @dd[a] = b
  end

  def list
    @dd.each do |i|
      puts i
    end
  end

  def sort
    aa = Array.new
    aa = @dd.sort
    @dd = aa
  end

  private

  def loadArray
    rr = Array.new
    rr << "one"
    rr << "two"
    rr << "three"
    rr << "four"
    return rr
  end  

end

Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
Tagged with: