Prawn: Table of Contents How To

Prawn is a ruby library for generating PDF documents. Although the library is still in beta state, it already has many useful features. Sometimes lack of documentation makes it hard to find right methods/properties.

Recently I needed to generate PDF documents with table of contents for my current project. It took me several hours of reading the source code and disassembling PDF documents to figure out how to do that. So I wanted to post short how-to here for me to remember and hopefully for others to save their time.

To build a table of contents you will need to create a dictionary of named destinations. Because at the time you render table of contents at the beginning of a document you don’t yet know at what page will be your 7th section. To add an entry to the Dests dictionary you use method ‘add_dest’. For example:

# page.dictionary means current page
# There are several dest_* methods to create a destination
add_dest('s34', dest_fit(page.dictionary))

And there are two ways to create a link to a named destination. The first one is to use text inline format:

text "<link anchor='s34'>Section 34</link>", :inline_format => true

This will create a clickable link to move the viewport to the defined destination. The second way is to use ‘link_annotation’ method. It allows you to create a clickable rectangular area defined by coordinates. You can specify a border as well. For example:

link_annotation([40,600,200,640], :Border=>[0,0,1], :Dest=>'s34')

Here you need to know the coordinates, but it’s the only way to create links on images.

The full example that you can try and run yourself follows:

require "#{File.dirname(__FILE__)}/example_helper.rb"
Prawn::Document.generate("toc.pdf") do
    font_size 14
    pad 10 do
        text "Table of Contents", :size=>20
    end
    text "* <link anchor='section1'>Section 1</link>", :inline_format=>true
    text "* <link anchor='section2'>Section 2</link>", :inline_format=>true
    link_annotation([40,600,200,640], :Border=>[0,0,1], :Dest=>'section3')

    start_new_page
    text "Section 1", :size=>20
    text 'Lorem ipsum dolor sit amet'
    add_dest('section1', dest_fit_horizontally(cursor, page.dictionary))
    move_down 300
    text "Section 2", :size=>20
    text 'Lorem ipsum dolor sit amet'
    add_dest('section2', dest_fit_horizontally(cursor, page.dictionary))
    start_new_page
    text "Section 3", :size=>20
    text 'Lorem ipsum dolor sit amet'
    add_dest('section3', dest_fit_horizontally(cursor, page.dictionary))
end

Comments off

Mutt is a bulletproof email client

Mutt is a powerful text-based email client. It is used mainly by system administrators and/or those who work remotely in terminal sessions. I wanted to try mutt as an email client for my daily work. And after a week of use I don’t want to return back to Apple Mail.

I have two email accounts and a dozen of aliases. In my configuration together with mutt I use the following applications:

  • fetchmail – to retrieve messages from different email accounts
  • dropmail – to filter and to save received messages locally in maildir format
  • msmtp – to send messages using smtp servers
  • mairix – to index and search emails
  • emacs – to edit new messages and replies
  • aspell – to spell check messages
  • lynx – to view html attachments

The result is a small, powerful, and flexible email client. I can name a few inconveniences though:

  • It takes time for mutt to parse big maildir boxes (during startup and when changing boxes only).
  • There is no simple way to view another email (in a separate window) while you reply to a message. As a workaround you can keep another instance of mutt running just to view emails.

In overall mutt fits very well in the way I manage my daily emails.

    Comments off

    Ruby on Rails helps Java to build momentum again

    As you probably know Java is not the best choice for small web applications. It has issues with deployment and hosting requirements. We can say that Java has lost its positions to PHP, Ruby, Python, and even .NET in this area. However Java remains the best solution for big enterprise projects.

    Today I was watching RailsConf 2007 keynote and Sun clearly explained why it loves Ruby and Rails. Very simple, if you need scalability, power, integration with existing enterprise systems then you can build your application in jRuby on Rails and get access to J2EE. And if your project is small you can write it in Ruby on Rails and get easiness of deployment and simple hosting requirements. In both cases you use Rails. Both Java and Rails win!

    So what technology are you going to use for your next project?

    Comments (1)

    7 things TextMate lacks that Emacs has

    I bought TextMate license recently. I wasn’t able to evaluate it thoroughly, but when the trial period has expired I paid. Mainly because I’ve read a lot of good reviews, and I liked its simplicity, elegance, and extensibility. The projects I was going to work on in TextMate were in Ruby, PHP, HTML, CSS, and JavaScript.

    However I like Emacs very much, and I have Aquamacs installed on my MacBook together with Ruby on Rails programming mode. This mode is designed very well and turns any work with Rails projects a pleasure. Unfortunately I noticed that the legacy of Emacs architecture makes extensibility of programming modes quite difficult. So here I come with features from Emacs that I would like to see in TextMate based on my Rails development experience. In hope that some day they will be implemented, as TextMate bundles are easy to modify.

    1. Rails project navigation. Emacs has shortcuts to show a menu of available controllers, models, stylesheets, and helpers. In TextMate I have to use Project Drawer, or Find in Project form, or Go To Alternate file command. Use of shortcuts is faster and more convenient. I think it’s possible to create commands in TextMate that will expand and focus on corresponding folder in Project Drawer.

    2. Open partial. Emacs can show a list of partials for current controller or view. It is very convenient especially when you work with AJAX views that depend mainly on partials.

    3. Find files. In Emacs you can find files within particular project areas, while TextMate by default searches all files in a project. It is a popular request to make Command-T in TextMate to work with predefined folders and/or filters.

    4. Incremental search. Although TextMate implements incremental search it doesn’t highlight found occurrences as Emacs and Vim do.

    5. Snippets. Rails mode for Emacs comes with many well thought out snippets, while TextMate has fewer of them and not that convenient.

    6. Tools support. I can start server or run a console right from Emacs. TextMate wraps rake commands and generator script nicely, but I have to open Terminal to run a console.

    7. Contextual menus. TextMate has sophisticated scope selectors, but when it comes to menus it doesn’t use them. For example right click on a code brings the same menu for all modes. The status bar menu could also change depending on active bundle.

    Comments (2)

    Accepting PayPal payments

    I’m glad to inform that now you can pay for the services with PayPal. Just select the number of hours you need on the payments page and click ‘Buy Now’ button. Then, when you are ready to check out, click ‘Check Out with PayPal’ button instead of ’2CO Checkout’ button. And as always you can pay with a credit card, PayPal is just one of the options.

    Comments off

    My New MacBook

    I was looking for a system that had Unix power under the hood and a polished Desktop interface, plus I wanted a laptop to add some mobility to my work. A MacBook was a viable option. So I went for it.

    I’m a power Windows user and I spent about 3 years working in Linux. However I was impressed by MacOS speed and efficiency, by Expose and Spotlight features, and by preinstalled software such as iLife. Still I couldn’t find a lot of tools I’ve got used to. Having Unix under the hood was a big saver. I added Terminal.app to the Dock, installed MacPorts and XCode tools, and then a lot of packages and command line tools from MySQL server to Midnight Commander. Another plus, MacOS comes with Java preinstalled and optimized. So I could install NetBeans right away.

    Then I had to find my way with a different keyboard shortcuts and a slightly different keyboard layout. I remapped CapsLock key to work as Ctrl and turned off option in the preferences for function keys to control hardware settings. After one week the MacBook keyboard is natural for me.

    One component that I still cannot understand is the Dock. When you open 30 applications at the same time and want to launch an application quickly from a list of 100 that you use every day — it becomes hard to manage. I searched through Mac forums and found that there exist tools that can help me with Dock. LaunchBar, Butler, and QuickSilver were their names. And I hope that Stacks feature in Leopard will be helpful as well.

    After I installed all the tools I needed for my work and learned MacOS a little I started to really enjoy my MacBook. However I lost several pieces of my hardware. My old laser printer had only LPT port which is not supported in modern computers. And my satellite receiver PCI card also wasn’t supported. But that’s all right because I’m going to upgrade them anyway.

    The next thing I’m going to try is to plug an external display for more convenient daily work at the desktop. Also I want to try different office suites (from Microsoft, Apple, and Sun) and Adobe applications for work with graphics.

    In overall I’m happy that I made the switch. In Windows I always was struggling with the lack of powerful command line support found in Linux. I used cygwin, but it wasn’t well integrated and had its glitches. In Linux I was spending a lot of time configuring the interface, installing different packages, drivers and servers. In my opinion Mac offers the best from the two worlds.

    Comments (2)

    WordPress Theme Generator

    I’ve been building many wordpress themes recently. And my code generators background suggested an idea for a wordpress theme generator.

    Many wordpress themes found online have flaws in several areas:

    • invalid HTML and/or CSS
    • no support for widgets
    • theme is easily broken with unusual content
    • the license doesn’t allow you to modify the theme

    And a theme generator can really help to resolve those issues.

    The idea is simple. Put some wizard dialogs that ask for a layout, size, color scheme, header image, icon set — and generate a complete wordpress theme. Sure, it is not something new. You can find several implementations with Google. But I want to make it professional. Backed by a full-featured code generator and spiced with some advanced features (such as Analytics and AdSense) such generator may become quite popular.

    Comments (1)

    Bill Gates and Steve Jobs together

    Spectacular joint interview with Bill Gates and Steve Jobs at D5 conference. Nice to see them humbled and showing so much respect to each other. There are video clips and a transcript you can read. You should see it.

    What Steve’s done is quite phenomenal. He has incredible taste and elegance. His ability to always come around and figure out where that next bet should be has been phenomenal. Apple really pursued the dream of building products that we want to use ourselves. He always seems to figure out where the next industry movement will be. The industry has benefited tremendously from his work.

    Bill Gates

    Comments off

    RailsConf 2007 is hot

    On May 17-20 RailsConf 2007 conference will be held in Portland. I was shocked that all 1200 seats were sold out yet in February! Ruby on Rails gets enormously popular despite its young age. Interestingly that Sun Micrsosystems, the company behind Java server-side technologies is a Diamond sponsor of the conference. And I must say that many Java developers have much sympathy for the Rails. JRuby development and other Ruby implementations in Java are good proofs of that. I hope that Ruby ease and speed of development, its growth of popularity and innovative ideas will meet Java maturity to a joy of all web application developers and their customers.

    Comments off

    Mass mailing – 5 things to remember

    To make your newsletters, product updates, and announcements easier to receive do provide the following things with each message you send:

    1. Simple mechanism to unsubscribe. Provide the detailed information how to unsubscribe from the future mailings and make this process really simple. Do test your application to make sure that unsubscription actually works.
    2. Information about where you got the address. Do remind your recipients why they wanted to receive your mailing. Gentle reminder such as: “you bought our product”, “you subscribed”, “you opted to receive” adds authenticity to your message.
    3. Contact information and privacy policy statement. In each message have a link to your site with your contact information and privacy policy statement. The contact information should include your names, the mailing address, and possibly a phone number – just email address is not enough.
    4. Appropriate recipient’s address with full name. Never send messages with recipient’s address in Bcc field. The address and the recipient’s full name should appear in To field.
    5. When sending HTML messages include the plain text copy in multipart alternative format. If recipient’s mail client is unable to show HTML messages then the plain text copy will be shown.

    These technics add credibility to your mailings, show your good intentions and professionalism. They let you avoid spam filters and reach more potential customers.

    Comments off