Archive for Ruby

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

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)