#! /usr/bin/env ruby # == Synopsis # stories2cards parses stories saved in the RSpec plain text story # format and saves a PDF file with printable 3"x5"" index cards # suitable for using in agile planning and prioritization. # # == Examples # This command outputs a PDF consisting of one card for each story and # narrative defined in stories.txt and saves it as stories.pdf # # stories2cards stories.txt # # Other examples # # stories2cards stories.txt -o /tmp/cards.pdf # stories2cards stories.txt --style=4up # # == Usage # stories2cards [options] text_file_with_stories # # For help use stories2cards -h # # == Options # -h, --help Displays help message # -v, --version Display the version, then exit # -o, --output=PATH Specify the path to the PDF file # to be created, defaults to storycards.pdf # -s, --style=1up|4up Defaults to 1up # -b, --[no-]borders Print borders (only has effect with 4up style # # == Author # Luke Melia # # == Copyright # Copyright (c) 2007 Luke Melia. Licensed under the MIT License # http://www.opensource.org/licenses/mit-license.php require 'optparse' require 'rdoc/usage' require 'ostruct' begin require 'pdf/storycards' rescue LoadError => le if le.message =~ %r{pdf/storycards$} root = File.dirname(File.dirname(File.expand_path(__FILE__))) $LOAD_PATH.unshift(File.join(root, "lib")) require 'pdf/storycards' else raise end end class App attr_reader :options def initialize(arguments, stdin) @arguments = arguments @stdin = stdin # Set defaults @options = OpenStruct.new @options.output = "storycards.pdf" @options.style = :"1up" end # Parse options, check arguments, then process the command def run if parsed_options? && arguments_valid? process_arguments process_command else output_usage end end protected def parsed_options? # Specify options opts = OptionParser.new opts.on('-v', '--version') { output_version ; exit 0 } opts.on('-h', '--help') { output_help } opts.on('-o', '--output [PATH]') { |path| @options.output = path } opts.on('-s', '--style [STYLE]', [:"1up", :"4up"]) { |style| @options.style = style } opts.on("-b", "--[no-]borders", "Print borders") { |b| options.borders = b } opts.parse!(@arguments) rescue return false true end # True if required arguments were provided def arguments_valid? return false unless @arguments.length == 1 return false unless File.exists?(@arguments[0]) return true end # Setup the arguments def process_arguments @source_file = @arguments[0] end def output_help output_version RDoc::usage() #exits app end def output_usage RDoc::usage('usage') # gets usage from comments above end def output_version puts "#{File.basename(__FILE__)} version #{PDF::Storycards::VERSION}" end def process_command style = :card_1up if @options.style == :"1up" style = :letter_4up if @options.style == :"4up" PDF::Storycards::Writer.make_pdf(@source_file, @options.output, :style => style) end end # Create and run the application app = App.new(ARGV, STDIN) app.run