Archive for the 'Ruby' Category

The Little Things in Life Rock

Nathan Weizenbaum was helping me with a few issues in a pet project I’m working on.

In the process, I ended up learning a really neat trick that Ruby can do.

To give you a bit of background, I’m working on a GTK Tray Icon. To make a menu spawn upon right-clicking the tray icon, you’d expect to see something like this:

require 'gtk2'

class TrayIcon
  def initialize
    trayicon = Gtk::StatusIcon.new
    trayicon.set_icon_name('folder')
    trayicon.set_tooltip('My Tray Icon')
    trayicon.signal_connect('popup-menu') { |button, activate_time| on_right_click(button, activate_time) }
  end

  def on_right_click(status_icon, button, activate_time)
    rc_menu = Gtk::Menu.new

    exit = Gtk::ImageMenuItem.new('Quit')
    exit_image = Gtk::Image.new(Gtk::Stock::QUIT, Gtk::IconSize::MENU)
    exit.set_image(exit_image)
    exit.signal_connect('activate') { Gtk.main_quit }
    rc_menu.append(exit)

    rc_menu.show_all
    rc_menu.popup(nil, nil, button, activate_time)
  end
end

But, the line 8th line (trayicon.signal_connect …) is a bit unwieldy. The thing is, we need those arguments to be passed for everything to work. And that’s where Ruby’s Proc handling comes in to save me. The same line can be re-written, and work, using the following line instead:

trayicon.signal_connect('popup-menu', &method(:on_right_click))

Adventures with Scribble!: Nothing Quite Like Playtime

I was feeling a little bored, so I opened up Scribble! (after a brief svn update) and decided to play around some.

I ended up making the RGB circle:

screenshot.png

While it obviously doesn’t blend to create that insanely cool effect, it looks cool anyway. πŸ˜€

During the process of this, however, something struck me… unless you’ve played with graphics before, none of the “average Joe Sixpack” users that Scribble! is designed for know the golden rule of computer graphics!

When you’re working with graphics on a computer, there’s a little “rule” that you operate under. The point of origin is the top left corner of the screen. There are of course many reasons for this, none of which I’ll trouble you with, but, to keep things brief, if you were to draw up a simple grid with X and Y axes, as far as computer graphics are concerned, you’re dealing with the IV (4th) quadrant.

Now that we’ve established that, looking at Scribble!’s code is easy.

size(360,300)
brush.stroke = 0, 0, 0, 0.7

This code establishes the two traits of the Scribble we’re working on before we start any drawing. We’ve set the size to 360 pixels wide and 300 pixels tall. Then we’ve set the stroke of the brush (don’t forget – this is still Ruby and method act on objects, in this case, the stroke is acting on the brush) to be black using RGB values (0 red, 0 green, and 0 blue is the combination for black) and have an opacity of 70%.

brush.fill = 1, 0, 1, 0.5
circle :center => [130,170], :radius => 75

Now, we begin by setting the color of our brush to Magenta (1 red, 0 green, 1 blue) and set its opacity to 50%. This next portion is a little bit trickier in terms of syntax, but it’s relatively simple to read. We’re creating a circle with a center point 130 pixels to the right of the origin and 170 pixels down from the origin. If we compared this to the coordinate sheet we envisioned earlier, our center point is at (130, -170). The next bit, the radius, is set to 75. Simple, no? The rest of the script is just placing two more circles of different colors on other parts of our canvas.

If you’ve got any interesting Scribbles you want to share, please comment! πŸ™‚

Adventures with Scribble!: The Basics of Basics

Scribble! has been undergoing many changes lately to prepare for the mystical and (at least in my case) anticipated 0.1 release.

But the important thing to remember about Scribble!, is that, just like Hackety Hack, its goal is to teach people how to program without breaking out the boring lectures about “Hey this is syntax. Do it.” It’s a tool for beginners to learn a little bit about graphics using Cairo and Ruby to have a little fun and expand their knowledge.

So, you ask me, how does Scribble! do it?

Pretend we take the following code and drop it into Scribble!:

#Set Canvas Size to 500x500!
size(500,500)
brush.fill = 0, 0, 0.9, 0.04 #Uses standard "Red, Green, Blue, Opacity" values
brush.stroke = 0, 0, 0, 0.1 #Same as above

#I like circles too! ^_^
30.times do
  circle :center => [rand(size[0]), rand(size[1])], :radius => (rand(size[0]) - 150)
end

#Draw a cool spiral thing that Evan Farrar came up with. B)
scribble(250,250) do |s|
  s.curve 250, 300
  s.curve 300, 250
  s.curve 250, 200
  s.curve 200, 250
  s.curve 250, 350
  s.curve 350, 250
  s.curve 250, 150
  s.curve 150, 250
  s.curve 250, 400
end

## And to top it off, a blue smiley face over everything!
scribble(100, 10) do |s|
  s.line(100, 60)
  s.jump(150, 10)
  s.line(150, 60)
  s.jump(80, 70)
  s.curve(125, 90)
  s.curve(170, 70)
end

The code is, of course, a little commented (mainly because I’m a nice guy, <3), so it shouldn’t take too much explanation. In fact, once you look at the image below, it shouldn’t take any at all!

Scribble! here, Scribble! there…. hell Scribble! everywhere!

So, I encourage you to go pick up Scribble from SVN and play around some:
svn co svn://hamptoncatlin.com/scribble/trunk scribble

To run it, cd to ‘/path/to/scribble’ and run ‘bin/scribble’. If you come up with anything neat, share it with me!

Fun Maths in Ruby

There’s a buddy of mine who I chat with frequently on AIM by the name of Josh, and well, one of our favorite activities (besides endless political debates and what-not) is essentially a giant pissing contest between Ruby and Python.

Josh is your typical die-hard Python fan. In his mind, there really isn’t anything that can compare.

Naturally, it’s only my God-given duty to show him how and why I prefer Ruby. πŸ˜‰

One of our recent contests involved the matter of a simple task: mathematically, find and print all numbers between 1 and 100, designating which were divisible by 3, 5, or both. He was the first one to write any code, and here’s what he came up with:

i=1
while i<=100:
    if i%15==0:
        print("%s is divisible by 3 and 5" % i)
    elif i%3==0:
        print("%s is divisible by 3" % i)
    elif i%5==0:
        print("%s is divisible by 5" % i)
    else:
        print i
    i=i+1

Fairly simple, right? Here’s my first iteration, which is basically a mirror of Josh’s code in Ruby:

i = 1
loop do
  i = i + 1
  if i >= 101
    exit
  end
  case i
    when i % 15 == 0
      puts("#{i} is divisible by 15")
    when i % 3 == 0
      puts("#{i} is divisible by 3")
    when i % 5 == 0
      puts("#{i} is divisible by 5")
    else
      puts("#{i}")
  end
end

As anyone can tell you, there are some inherent issues with that code. Let’s talk about them:

  • The incrementation of i (i = i + 1) should never come at the beginning of a loop. It’s bad practice. I’m not going to go off into a huge rant as to why – it’s been covered and explained in so many text books and what-not that it’d be a waste of my time.
  • The code doesn’t intuitively “know” to stop at 100. It manually checks every single time the process is run if we’re above 100, which is unnecessarily redundant and time-consuming. Or just plain unnecessary.
  • Injecting a string was entirely unnecessary. “puts(i)” would have achieved the same effect in cleaner code.

To summarize: there are better ways of doing it. One other way is to use a ‘while’ loop, but that’s not the best way to do it either. In the end I settled for this implementation using a “for foo in bar” loop:

for i in (1..100)
  if i % 15 == 0
    puts("#{i} is divisible by both 3 and 5")
  elsif i % 3 == 0
    puts("#{i} is divisible by 3")
  elsif i % 5 == 0
    puts("#{i} is divisible by 5")
  else
    puts(i)
  end
end

Of course, after I did this, Josh realized he could do the same in Python:


for i in range(1, 101):
    if i%15==0:
        print("FizzBuzz")
    elif i%3==0:
        print("Fizz")
    elif i%5==0:
        print("Buzz")
    else:
        print i

And for kicks, he even did it in LISP:

(defun count()
	(setq i 1)
	(while (<= i 100)
		(cond
			((= 15 (gcd i 15)) (princ "i is divisible by 5 and 3n")

			((= 5 (gcd i 5)) (princ "i is divisible by 5n")

			((= 3 (gcd i 3)) (princ "i is divisible by 3n")

			(t (princ i) (princ "n") )
		)
		(setq i (+ 1 i))
	)
	(princ)
)

Let’s analyze the code (that is, my Ruby code), shall we?

The code opens with our main loop, which is a fairly readable type of loop. Simply put, it translates into “For the variable ‘i’ in the range of numbers 1 through 100, including 1 and 100, do the following”. Fairly easy to understand right? That’s Ruby for you. πŸ˜‰ From there, the code breaks down into a simple conditional where it checks first to see if the number is divisible by both 3 and 5. It goes on to check if it is divisible by 3 or 5. Finally, if none of the above is true, then the number is printed.

It’s important to understand why this code is better, and more efficient. First and foremost, it maintains readability, which is always a must when working with code, while at the same time using some of the nicer features in Ruby in order to avoid redundant work. The biggest change by switching to this type of loop is that the loop now knows to stop at 100 without us manually having to assert that the program exit. We also were able to remove all the redundant incrementation of ‘i’ because it’s factored into our loop already.

So why am I writing about something so trivial as a pissing contest? Because it’s an important tool for learning about how to teach coding, and more specifically Ruby. Since I’m still learning (albeit at a fairly rapid rate), I’m essentially a perfect guinea pig. Until you break down things like “for foo in bar” into human-understandable syntax, you’ll find that you will be going at problems from a longer, more difficult angle. High-level languages have very strong and usable syntax for a reason. However, you’ve got to make a conscious effort into learning more than just the most basic of the basics. The quirks might not be enjoyable to learn, but they’ll improve your code ten-fold.

PS. Thanks to Nathan for tipping me off about using “for foo in bar” instead of while! πŸ˜‰

Hackety Hack, Meet Linux

Hackety Mouse!After much wait and whining (let’s face it, it’s in high demand!), _why released the first Linux version of Hackety Hack. For those of you who, for some reason completely beyond me, aren’t accustomed to Hackety Hack (or _why for that matter!), Hackety Hack is pretty much the coolest thing since sliced bread.

To start understanding what motivates _why and the other Hackety Hackers, you’ve got to read up on two very important documents which have caused not just controversy but an entire revolution in the way many people think about coding and programming in general.

The first of these is the much-debated and much-beloved essay by why called “The Little Coder’s Predicament“. If you haven’t read this essay yet, go do it now. I’ll wait. Yes, I’m still waiting, now get a move on. Let us think on what _why presents here:

  • Coding shouldn’t be the “dirty little secret” of computers; it should be celebrated and available to everyone.
  • Coding shouldn’t be complicated. A simple task, such as playing a song, should be one line.
  • Code should be not just shared, but shared easily. What’s the point in coding something that nobody will ever see in action?

In today’s world, this sort of thing doesn’t really sound so far-fetched… but you’ve got to keep in mind that _why was writing about this nearly four years (to the day) ago. This was back in the days when Microsoft Office 2003 was the newest thing and Pentium 4 wasn’t considered an old processor.

If “The Little Coder’s Predicament” was the beginning of a prolific movement that’s shaped the entire landscape of learning how to program, then this next bit of genius was what really got the gears turning. If one reads “The Hackety Manifesto“, you’ll immediately notice that it doesn’t talk about anything new. That’s true. It doesn’t; not really. Instead, what it does is further build upon _why’s prior musings in 2003 and extend them into the basis for an application that could revolutionize the way people think about programming.

So what are the Hackety Laws?

  • Beginners should be greeted to Hackety Hack by a cartoon character. (For the sake of argument, let’s call this character: Hacky Mouse.)
  • Also, helpful sentences. And full sentences with a period.
  • Hackety Hack is fundamentally a browser and a programming language. For now, Gecko and Ruby.
  • I’m only using Ruby because I know it. Hopefully, more languages can be added!
  • Again, this isn’t about Ruby, it’s about simply offering a place for plainspeople to tinker with code.
  • IDEs are a disaster. Newbs should see only one non-scary window free of tree controls and pinned windows and toolbars.
  • As such, we want to stay away from project files and makefiles, the trappings of an IDE.
  • Hackety Hack also adds simple libraries for common things.
  • Common things are one-liners.
  • Keep args and options to a minimum.
  • In Ruby, blocks should be used to open up a method to more advanced possibilities.
  • Help files are clean, short, simple. Lots of short examples. No frames.
  • While all bug tickets are helpful and great, I just value tickets from beginners to a greater degree.
  • Hackety Hack is free and will remain free henceforth.

Sounds simple, right?

It’s not.

Think about it – out of all the applications you’ve ever written, or APIs, or libraries, how many times has this really been the case? Once? Twice? The fact of the matter is, clean, simple, easy-to-read code is one of the lost arts that’s only very slowly being relearned and practiced widely, and it’s a shame that it’s taken this long.

So where does Hackety Hack come in?

Hackety Hack is neat if for one thing – it’s a wonderful teaching tool. Hackety Hack was designed to be a simplified front to the Ruby language that was designed in such a way that even the noobiest of noobs and the dullest of gardening tools could code together some very neat, working programs. It’s true to its words in the manifesto – downloading an MP3 or even a simple “Hello world!” program is one line. Obviously, since, at least in the case of the former, Ruby cannot do this out-of-the-box, Hackety Hack comes preloaded with all sorts of neat libraries that one can just call as a simple object inside Hackety Hack. Like the front page boasts, you can write a simple blog in all of six lines of code:

blog = Table("MyBlog").recent(10)
Web.page {
  blog.each do |entry|
    title entry[:title]
    puts entry[:editbox]
  end
}

So, to finally get to the point, after much wait and begging and other forms of worship, _why has blessed we Linux users with our first release of Hackety Hack. For a long time it was, very sadly, a Windows-only application, but now, as of this week, we can finally enjoy the bliss that is Hackety Hack.

hackety1 hackety4!hackety2! hackety3!

Amazingly Awesome Screenshots Thanks to Nathan Weizenbaum!

(You can also click on any of those for their full versions instead of thumbnails!)

 

Ubuntu Feisty users can pick up the tarball here.

To run Hackety Hack, you’ll need to install ‘libwxgtk2.8-0’ and ‘libwxbase2.8-0’ from the universe repository. Once you’ve done that, you can run Hackety Hack from wherever you untarred it to with the following:

LD_LIBRARY_PATH=/usr/lib/firefox:. ./hacketyhack

People on other distributions, assuming they know where the firefox files are kept, can just change the LD_LIBRARY_PATH as necessary. πŸ™‚

Note: There seems to be an issue with the libwx stuff in Gutsy, so if you’re a brave folk like myself, you won’t be able to enjoy the wonderful gooey, ooey sensation that is Hackety Hack. If you’re interested, I’d advise just paying attention to this thread on the Talkety Talk forum.

Hackety Mouse Demands You Start Hacking Right Away!
hackety 5?!?!?
You heard the rodent. Hop to it!

Write on the Walls! … and the Ceiling … and hell, just Scribble!

For those of you who aren’t always up-to-date on those wonderful up-and-comers in the world of software, you should be ashamed because you are missing out on some great stuff. Really. Get out and live a little!

One of those Great-Projects-You’ve-Never-Heard-Of is developed by an Interweb buddy of mine by the name of Nathan Weizenbaum: it’s called Scribble!

When he first wrote about Scribble!, I was immediately excited. While of course it’s a fairly neat sandbox for playing with Ruby and Cairo rendering, the best application of Scribble! is the one in the classroom. No – not drawing on the walls! Scribble has the potential to be a ridiculously good teaching aid for students with a little knowledge about Ruby’s syntax. Like Nathan noted in his post, Scribble! is to graphics what Hackety Hack is to general application writing.

Of course, with the project still in its immediate infancy, Nathan (as well as Jon Leighton, who is the only other consistent hacker for the project at the moment) is a bit busy working on the actual back-end of the application as opposed to writing Joe Sixpack-friendly walkthroughs to explain things like “How to use a method: for Dummies”.

Scribble! for Dummies!

Still, Scribble! is an exciting project written in possibly the coolest language ever (if you have to ask what the language is, don’t bother leaving a comment :P). The only thing it could really use at this point is more developers – the rest will come in due time. πŸ™‚

Speaking of Scribble! development, I finally got my hands muddy today with a patch to implement GTK Source View highlighting and a few other things in the text display, which should make its way into SVN in the next 24 hours or so:

_TWO_ images in the same post?! Madness!

If you’re interested in developing, or even just playing around, you can checkout trunk from the subversion repository here:

svn co svn://hamptoncatlin.com/scribble/trunk scribble

Keep in mind that you’ll need the Ruby-Cairo and Ruby-GNOME2 and Ruby-GTK stuff to run it.

The google group can be found here.