The Accidental Rubyist

invalid byte sequence in UTF-8

Archive for September 2008

Charming ruby with curses

with 12 comments

The other day I did something good. I fished out my Programming Ruby book and skimmed through it. I found many interesting things there, and i was drawn to this sample curses program. I downloaded it – a paddle that moves up and down.

In about 2 hours, I had a snake program up and running. The player (a snake) navigates around an empty screen which has some Sprites — good and bad. He gobbles them up. The time is displayed on top (how very professional!) and the players lives etc. You can download and play it if you like (for absolutely free).

Python seems to provide a lot more with its curses wrapper. Anyway, to get more out of ruby curses you need to install ncurses. (sudo gem install ncurses). I am on the lookout for more work done with ruby using ncurses, especially libraries/code that could help me create forms with menus — something close to pine or nano, an editing textarea widget like nano would be great.

Would it be of any use to anyone (or the ruby community) if I ported some of python’s ncurses wrapper to ruby ? I assume if i can understand some python (I once ported pythons Medusa, aka asyncore, to Java successfully). Suggestions and some details would be welcome.

Edit: See rbcurse on rubyforge or github.

Advertisements

Written by totalrecall

September 12, 2008 at 11:50 pm

Posted in ruby

Modifying choice (command-line parser)

leave a comment »

I liked choice so much, I didn’t want to leave it (I need unparsed args). So I went back to the source code. And then came back to my timeconverter. I realized I could clean up ARGV based on Choice.choices. This worked.

1 module Choice
2   def get_unparsed_args(args)
3     flat=Choice.choices.to_a.flatten
4     args.delete_if { |a| a[0].chr == '-' || a[0,1] == '--' || flat.include?(a) }
5     args
6   end
7 end
8
9 

If this is a bad idea, please tell me, this is the first time I have tried such a thing. It worked, but I would have copy this to each program. Anyway, I have tested it with only one program which has limited options.

I can call this method giving it ARGV and get back an array with only unparsed options which I could then process in a loop.

So it looks like I will not be evaluating other libraries as of now. I would be grateful if Chris would give us a way of getting the unparsed args. I don’t know how correct this method is. Needs testing in many scenarios.


# substitute “foo” with “bar” ONLY for lines which contain “baz”
$ cat | ruby -pe ‘gsub(/foo/, “bar”) if $_ =~ /baz/’

Written by totalrecall

September 8, 2008 at 10:41 pm

Posted in ruby

Command-line option parsing experiences with clip

with 2 comments

I went through the one examples provided with clip . Looked very promising and simple. Until I applied it to my timeconverter program. Quick observations:

1. in the example “host” should be “server” (typo).
2. If using ruby -w, there are too many uninitialized variable warnings
3. Can’t reuse “-h”, yet on typing “-h” on prompt gives an error
4. multiple params to an option must not have any spaces. That allows clip to know the remainder (unparsed args) which choice has a problem giving me since it allows spaces between multi options. Fine with me.
5. No fancy printing of options: common and specific etc with separators, which is fine with me.
6. Allows for optional and required options, and flags which is good.

My timeconverter was using choice , a fine commandline parser, with one failing that I cannot get the unused arguments which I needed. I converted the choice portion to clip and began running the program. My program essentially converts time from one time zone to another, taking into account daylight saving. However, it can optionally print country codes, timezones for a country etc to help in using the main function. These are like independent commands.

The clip concept of “optional” is only for configuration values which will be used in the program such as port, host etc. All optional options require a default value to be specified, so i have no way of knowing if it was triggered or not. If the user enters the optional flag without specifying a value there is no way of knowing that. In such cases, I can only ask the user to type –help, since I don’t know what went wrong.

When i first gave the prog name on the prompt with no params, I expected the help screen. But execution went into the optional paths!

Flags give eval warnings if not used. You cannot give a default for them.

Options and their parameters require a space between, a “=” cannot be used as “–port=8080”. This makes the clip program source simple and short, but took me some time to debug. It just went into the not valid block leaving me wondering!

I will summarize saying that clip is great if your program has one action, and many config values that can default (which is probably the case most of the time). If your program has multiple optional execution paths, then this may not be the correct tool for you.

# number each line of a file (left justified).
$ cat | ruby -ne ‘printf(“%-6s%s”, $., $_)’


HTML.vim,
mtsend.py

Written by totalrecall

September 8, 2008 at 10:38 pm

Posted in ruby

Rewriting shell-scripts in ruby

leave a comment »

Just a note to myself (before I start some real work), that I’ve gotta rewrite some of my most used shell scripts in ruby, and write future ones in ruby. Reasons for frustration with bash scripting:

– if and loop syntax gets me
– unpredictable behavior of unix commands due to differences between gnu, macport and bsd versions. The options differ (take date for example, or split). The same program could pick up one egrep when running as a cronjob and another when executed by me on the prompt.
– regexp: one is no longer used to escaping + in a regexp as in “[0-9]\+”. Which reminds me that “\d” does not seem to work everywhere.
– File name and cat loops: data in loops gets split on spaces, have to go back and change delimiter to newlines.
– sensitivity to spaces
– updates to os x or macport often broken (one version of curl has stopped doing SSL due to some reason I forget — took ages to debug)

Writing these programs in ruby will help me learn faster. I could use highline for this work


Code comment:
// we are such morons. Wiz97 underwent a redesign between IE4 and IE5
http://www.kuro5hin.org/story/2004/2/15/71552/7795

# reverse order of lines (emulates ‘tac’) IMPROVE
$ cat | ruby -ne ‘BEGIN{@arr=Array.new}; @arr.push $_; END{puts @arr.reverse}’

Written by totalrecall

September 8, 2008 at 12:43 pm

Posted in ruby, unix

Ruby command-line parsing (update)

with 5 comments

The issues with optiflag and choice: regarding determining unparsed arguments seems to have been posted in their respective forums a year or 2 back. But no response from authors. Are these 2 projects abandoned ?

I dipped into the source code of choice (parser.rb) to see if i could figure out how to extract the args, but after trying out variations on the command line, and print statements, it does not look like an easy task – not for me at least (a newbie). The author is a big-shot and busy (and very cool looking), so I guess he won’t be reading my mail for some time (http://www.youtube.com/watch?v=-Reg0yhJw4s !).

The comments on this page led me to some excellent options such as:
Thor: by whycat’s (yehuda katz). It’s a great tool, maps commands on the CL to ruby methods. It is executed like rake: thor prog options. Something definitely to use in the near future.
clip: This one does state in its help that it allows the remainder args to be accessed. It seems to simplest of all.
– I once again looked at trollop. It does not do any validations, and I am not sure whether the remainder args are accessible or not. What i can see is that I would have to have a separate switch case for all the options.
– I once again looked at Commandline. It begins to look more appealing after the issues I have faced with the others.
– I gave a much closer look at cmdparse : looks great for commands and subcommands as in rake and webgen (its written by the webgen author who is very active and responds immediately). Could not figure out whether it will give me the remainder or not.

My next step will probably to give clip and trollop a try. Along the way, I discovered interesting things such as SproutCore (a ruby javascript framework), gambit, elif (a backward file reader), SimpleConsole, python’s cly, read up more on JSON …

As can be seen from my sig on git, I looked at the tutorials of several revision control systems such as bazaar, mercurial, git and subversion and finally decided to try out git after all. Have been using rcs until now.


I’m an egotistical bastard, and I name all my projects after myself. First Linux, now git.
— Linus Torvalds

# print file except for blank lines
$ cat | ruby -pe ‘next if $_ =~ /^\s*$/’


HTML.vim,
mtsend.py

Written by totalrecall

September 8, 2008 at 12:29 pm

Posted in Uncategorized

Command-line parsing: choice and optiflag

leave a comment »

For some reason, I decided to go for choice, for a tiny time converter (DST) program I had put together. choice has a nice easy way of setting up the options configuration. Easy to remember, no syntax. It has the ability to filter and validate the args. Being a newbie, however I did waste an hour trying to access the param inside the action block using Choice.choices[:param] which was not yet set up. Finally, it dawned on me to use value as in:
action do |value|
as in:

  option :countries do
    long '--countries=[PATTERN]'
    desc 'List all countries, or those matching a pattern'
    action do |value|
      if value == true
        puts TZInfo::Country.all.sort
      else
        puts TZInfo::Country.all.sort.find_all{|item| item.name =~ /#{value}/;  }
      end
      exit
    end
  end

My bad!
Later I got stuck for another hour trying to figure out why my program ran fine when the user entered no timezone (and the default was used), but gave wrong results when he entered it.
Finally I printed ARGV[0] and discovered that choice does not consume ARGV as it parses. I searched the docs, examples etc but there was no mention of how to access unused params.
The command is executed as:


./timeconverter.rb --from="America/New_York" "12:00 PM"

The “–from” is optional and defaults to America/New_York. The “12:00 pm” is not an option. When I used OptionParser, “12:00 PM” would be the only item left on ARGV.

So I thought about shifting ARGV myself. However, I do not know when the user enters “-f ” or “–from=” or the default is invoked. Each would result in “12:00 PM” being in a different slot on ARGV.

A bit rattled by this, I installed Optiflag and played with the samples. Optiflag, too does not shift ARGV, although it does maintain a hash called ARGV.flags and I could remove the flags and values from ARGV so it leaves me with “12:00 PM”. That said, optiflag does print the help very well. If i have 3 mandatory flags, and I enter only one, it only prints out the 2 I have not entered, not the entire options list.

At this stage, I did give yet another visual look at CommandLine and also at GetOpt::Declare — which just blows my mind away, but its not for this lifetime. Perhaps, I’ll just go back to OptionParser or even getoptslong. Commandline parsing should not take me more time that my program itself. I sent a mail to chris of choice.rubyforge.org, waiting for an answer.


# convert Unix newlines (LF) to DOS format (CR/LF)
# – strip newline regardless; re-print with dos EOL
$ cat | ruby -ne ‘BEGIN{$\=”\r\n”}; print $_.chomp’

Written by totalrecall

September 6, 2008 at 9:30 am

Posted in Uncategorized

Command-line parsing: choosing a ruby library

with 7 comments

I started with getoptlong, but lately decided to try something that would make life simpler. I need a parser that gives me options for:

  • mandatory flags

  • optional flags

  • switches

I used OptionParser for the ruby csplit program. The code of OptionParser is probably longer than the program code itself. It also does not let me define a mandatory flag. So I need to put in some code myself. Error messages for missing option parameters come with line numbers like program bugs. OptionParser is good, it will cast to a int, float, etc, but I am looking for something easier.
Looked at trollop — very little documentation, probably does not support the above.
Looked at Optiflag: this looks good. Besides allowing for optional and mandatory flags, it even allows for defining validations and lists for parameters.

Their page lists other alternatives, and another I really liked is Choice. Choice has very easy to use syntax. One does not need to remember what position some configuration needs to go. It may not look rubyish, but it is very easy to work on and remember. However, that page specifies that it may not be stable. It also gave me a link to a command-line library for taking input and validating it named Highline.

The ruby forum page (article dated 2005) also talked of CommandLine, looks good, but a needs looking into in greater detail to see what all is offered with ease, without needed to get into the low-level section.

cmdparse seems to be the most advanced – certainly not for me. Or maybe I’ll just come back to getoptlong. With getoptlong, i need to maintain my own help/usage string. Options are defined in one array. Actions on options are defined in a separate case switch. Three places to update for each change.


# grep for foo AND bar AND baz (in order)
$ cat | ruby -pe ‘next unless $_ =~ /foo.*bar.*baz/’

Written by totalrecall

September 5, 2008 at 2:08 pm

Posted in ruby