Archive for the ‘Projects’ Category

Introducing ANSI Tags

This Thursday I was bored. So I decided to make a gem with a very simple purpose: Convert ANSI codes to HTML. I did some research on the topic and found that ANSI codes is capable of more than just outputting colored and styled text in the console. According to this Wikipedia article you can also use it for moving the cursor, scrolling, deleting output, and other things.

Due to the nature of HTML, ANSI Tags doesn’t aim to convert that sort of codes. ANSI Tags can only convert one type of codes, specifically “SGR” or “Select Graphic Rendition” which changes color, style, and visibility of console output. Here’s the list of ANSI SGR codes:

  • 0 resets everything. Black text on white background, not bold, not underlined, not italic, not hidden. (supported)
  • 1 makes output bold. (supported)
  • 2 makes output faint/thin. (not supported)
  • 3 makes output italic. (supported)
  • 4 makes output underlined. (supported)
  • 5 & 6 makes output blink slow and rapid respectively. (not supported!)
  • 7 swaps foreground and background colors. (supported)
  • 8 makes the output invisible. (supported)
  • 21 makes output double underlined. (not supported)
  • 22 resets the font weight of the output. (supported)
  • 24 turns underline off. (supported)
  • 25 turns blink off. (not supported, obviously)
  • I don’t know what 27 does and it’s not supported.
  • 28 “reveals” the output, a.k.a. stops it from being hidden. (supported)
  • 30-37 sets the foreground color to one of the seven low intensity colors. (supported)
  • 39 resets the foreground color to the default low intensity color. (supported)
  • 40-47 sets the background color to one of the low intensity colors. (supported)
  • 49 resets the background color to the default low intensity color. (supported)
  • 90-97 sets the foreground color to one of the high intensity colors. (supported)
  • 99 resets the foreground color to the default high intensity color. (supported)
  • 100-107 sets the background color to one of the high intensity colors. (supported)
  • 109 resets the background color to the default low intensity color. (supported)

Phew, that’s a lot of codes. Enough talk. Let’s install ANSI Tags:

sudo gem install ansitags --source http://gemcutter.org/

ANSI Tags has absolutely no dependencies and the code is ultra simple so it should work on any platform. Here’s how to use it:

"\e[1mHere's some text that's been made bold using ANSI escape codes.\e[0m".ansi_to_html
=> "<pre><span style="font-weight: bold;">Here's some text that's been made bold using ANSI escape codes.</span></pre>"

In this example we’re making use of two escape codes: 1m and 0m. As it says in the list above, 1m makes output bold, 0m resets everything. ANSI Tags always uses the span tag to change output style, which allows it to just output one span end tag for each ANSI code it has encountered when it reaches the 0m escape code:

"\e[1m\e[32mGreen, bold text\e[0m".ansi_to_html
=> "<pre><span class="font-weight: bold;"><span class="color: #00FF00;">Green, bold text</span></span></pre>"

In addition, ANSI Tags will close all unclosed span tags automatically so the HTML validator won’t complain:

"\e[3m\e[44mI want valid HTML!".ansi_to_html
=> "<pre><span class="font-style: italic;"><span class="background-color: #000080;">I want valid HTML!</span></span></pre>"

That’s about it. ANSI Tags is to be found on GitHub and I hope you’ll enjoy it.

Introducing Virtual Attribute Cache

This is really old news but I’m aiming to have one post per open source project on this blog.

Virtual Attribute Cache is the ultimate way to cache Active Record virtual attributes. The idea is simple. Say, for example, you have a first_name and a last_name column. Then you might have a full_name virtual attribute that joins first_name and last_name plus a full_name column in your database which stores the cached value of the full_name virtual attribute. With va_cache that would be accomplished like this:

class Person < ActiveRecord::Base
  cached_virtual_attribute(:full_name, :expire_if => Proc.new { |p| p.first_name_changed? || p.last_name_changed? }) do
    [first_name, last_name].join(' ')
  end
end

Basically, you need to provide va_cache with three things:

  1. The name of the virtual attribute to cache.
  2. When to expire the cache (the Proc will be evaluated in a before_save callback.)
  3. How to calculate the value of the virtual attribute.

If you don’t like to have Proc’s in the middle of your method calls you can use this alternative syntax:

class Person < ActiveRecord::Base
  cached_virtual_attribute :full_name, :expire_if => :first_name_or_last_name_changed do
    [first_name, last_name].join(' ')
  end

  def first_name_or_last_name_changed?
    first_name_changed? || last_name_changed?
  end
end

Final notes:

  • Don’t use va_cache with simple stuff like full names, obviously.
  • If you pass a symbol to the :expire_if a question mark will be appended automatically.
  • Seriously, go look at the source code. It’s extremely simple.

That’s it. Enjoy!

Introducing Gyro Gearloose’s Little Helper

Little Helper is a new plugin of mine that keeps your views DRY by defining helper methods that you always end up adding manually anyway. Currently it has three handy methods but I’m planning to extend it along the way.

#title

Lets you put the same text in your <hX> headline and <title> tags:

<h1><%= title 'Hello, World!' %></h1>
=> <h1>Hello, World!</h1>

<%= title :site => 'Some Site' %>
=> <title>Some Site &mdash; Hello, World!</title>

#stylesheet & #javascript

Lets you specify what stylesheets and JavaScripts a page depends on:

<% stylesheet 'foo', 'bar' %>
<% javascript 'foo', 'bar' %>

#stylesheets & #javascripts

Given you have specified a couple of stylesheet that a specific page depends on in your view:

<% stylesheet 'view_specific_stylesheet', 'another_view_specific_stylesheet' %>

And you’ve put this in your layout:

<%= stylesheets 'additional_stylesheet' %>

Little Helper will link to the following stylesheets:

  • application.css
  • screen.css
  • print.css (with media=”print”)
  • ie.css (wrapped in a conditional comment)
  • additional_stylesheet.css
  • controller.css
  • controller/action.css
  • view_specific_stylesheet.css
  • another_view_specific_stylesheet.css

#javascripts works the same way, except if you pass a symbol to it, it’ll treat it as a package, e.g. :defaults, just like #javascript_include_tag.

That’s it. Go ahead and check the plugin out at GitHub.