oyster 0.9.1 → 0.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +14 -3
- data/Manifest.txt +4 -4
- data/README.txt +26 -21
- data/Rakefile +1 -1
- data/lib/oyster.rb +6 -3
- data/lib/oyster/specification.rb +37 -18
- data/test/test_oyster.rb +8 -1
- metadata +13 -11
    
        data/History.txt
    CHANGED
    
    | @@ -1,6 +1,17 @@ | |
| 1 | 
            -
            ===  | 
| 1 | 
            +
            === 0.9.2 / 2009-06-19
         | 
| 2 2 |  | 
| 3 | 
            -
            *  | 
| 3 | 
            +
            * Use Curses to set the width of help output.
         | 
| 4 | 
            +
            * Fix some formatting and layout bugs in help text.
         | 
| 4 5 |  | 
| 5 | 
            -
             | 
| 6 | 
            +
             | 
| 7 | 
            +
            === 0.9.1 / 2009-01-30
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            * Ruby 1.9 compatibility fixes.
         | 
| 10 | 
            +
             | 
| 11 | 
            +
             | 
| 12 | 
            +
            === 0.9.0 / 2008-07-17
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            * Initial release. Includes option parsing for flags, strings, ints,
         | 
| 15 | 
            +
              floats, globs, files, shortcuts and subcommands. Automatically
         | 
| 16 | 
            +
              renders man-page-style help to stdout with the -h flag.
         | 
| 6 17 |  | 
    
        data/Manifest.txt
    CHANGED
    
    | @@ -5,13 +5,13 @@ Rakefile | |
| 5 5 | 
             
            lib/oyster.rb
         | 
| 6 6 | 
             
            lib/oyster/specification.rb
         | 
| 7 7 | 
             
            lib/oyster/option.rb
         | 
| 8 | 
            +
            lib/oyster/options/array.rb
         | 
| 9 | 
            +
            lib/oyster/options/file.rb
         | 
| 8 10 | 
             
            lib/oyster/options/flag.rb
         | 
| 9 | 
            -
            lib/oyster/options/string.rb
         | 
| 10 | 
            -
            lib/oyster/options/integer.rb
         | 
| 11 11 | 
             
            lib/oyster/options/float.rb
         | 
| 12 | 
            -
            lib/oyster/options/file.rb
         | 
| 13 | 
            -
            lib/oyster/options/array.rb
         | 
| 14 12 | 
             
            lib/oyster/options/glob.rb
         | 
| 13 | 
            +
            lib/oyster/options/integer.rb
         | 
| 15 14 | 
             
            lib/oyster/options/shortcut.rb
         | 
| 15 | 
            +
            lib/oyster/options/string.rb
         | 
| 16 16 | 
             
            lib/oyster/options/subcommand.rb
         | 
| 17 17 | 
             
            test/test_oyster.rb
         | 
    
        data/README.txt
    CHANGED
    
    | @@ -1,18 +1,22 @@ | |
| 1 1 | 
             
            = Oyster
         | 
| 2 2 |  | 
| 3 | 
            -
            http://github.com/jcoglan/oyster
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            === Description
         | 
| 3 | 
            +
            * http://github.com/jcoglan/oyster
         | 
| 6 4 |  | 
| 7 5 | 
             
            Oyster is a command-line input parser that doesn't hate you. It provides a simple
         | 
| 8 6 | 
             
            API that you use to write a spec for the user interface to your program, and it
         | 
| 9 7 | 
             
            handles mapping the input to a hash for you. It supports both long and short option
         | 
| 10 8 | 
             
            names, subcommands, and various types of input data.
         | 
| 11 9 |  | 
| 10 | 
            +
             | 
| 11 | 
            +
            === Installation
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              sudo gem install oyster
         | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| 12 16 | 
             
            === Features
         | 
| 13 17 |  | 
| 14 18 | 
             
            * Parses command line options into a hash for easy access
         | 
| 15 | 
            -
            * Supports long ( | 
| 19 | 
            +
            * Supports long (<tt>--example</tt>) and short (<tt>-e</tt>) names, including compound (<tt>-zxvf</tt>) short options
         | 
| 16 20 | 
             
            * Supports subcommand recognition
         | 
| 17 21 | 
             
            * Can parse options as booleans, strings, arrays, files, globs
         | 
| 18 22 | 
             
            * Automatically handles single-letter shortcuts for option names
         | 
| @@ -20,12 +24,13 @@ names, subcommands, and various types of input data. | |
| 20 24 | 
             
            * Is easily extensible to support custom input types
         | 
| 21 25 | 
             
            * Automatically outputs man-page-style help for your program
         | 
| 22 26 |  | 
| 27 | 
            +
             | 
| 23 28 | 
             
            === Usage
         | 
| 24 29 |  | 
| 25 30 | 
             
            You begin your command-line script by writing a spec for its options, layed out
         | 
| 26 31 | 
             
            like a Unix manual page. This spec will be used to parse input and to generate
         | 
| 27 | 
            -
            help text using the  | 
| 28 | 
            -
            spec API. You can use as much or as little of it as you like, none of the fields
         | 
| 32 | 
            +
            help text using the <tt>--help</tt> flag. This example demonstrates a wide range of
         | 
| 33 | 
            +
            the spec API. You can use as much or as little of it as you like, none of the fields
         | 
| 29 34 | 
             
            are required.
         | 
| 30 35 |  | 
| 31 36 | 
             
              require 'rubygems'
         | 
| @@ -45,19 +50,21 @@ are required. | |
| 45 50 | 
             
                EOS
         | 
| 46 51 |  | 
| 47 52 | 
             
                flag    :verbose,   :default => false,
         | 
| 48 | 
            -
             | 
| 53 | 
            +
                        :desc => 'Print verbose output'
         | 
| 49 54 |  | 
| 50 55 | 
             
                flag    :recurse,   :default => true,
         | 
| 51 | 
            -
             | 
| 56 | 
            +
                        :desc => 'Enter directories recursively'
         | 
| 57 | 
            +
                
         | 
| 58 | 
            +
                shortcut :all, '--verbose --recurse'
         | 
| 52 59 |  | 
| 53 60 | 
             
                string  :type,      :default => 'f',
         | 
| 54 | 
            -
             | 
| 61 | 
            +
                        :desc => 'Which type of files to move'
         | 
| 55 62 |  | 
| 56 63 | 
             
                integer :status,    :default => 200,
         | 
| 57 | 
            -
             | 
| 64 | 
            +
                        :desc => 'Tell the program the status code to return'
         | 
| 58 65 |  | 
| 59 66 | 
             
                float   :quality,   :default => 0.5,
         | 
| 60 | 
            -
             | 
| 67 | 
            +
                        :desc => 'Level of compression loss incurred when copying'
         | 
| 61 68 |  | 
| 62 69 | 
             
                glob    :files,     :desc => <<-EOS
         | 
| 63 70 | 
             
                Pattern for selecting which files to move. For example, to select all the
         | 
| @@ -87,8 +94,8 @@ are required. | |
| 87 94 | 
             
              end
         | 
| 88 95 |  | 
| 89 96 | 
             
            Having defined your spec, you can use it to parse user input. Input is specified
         | 
| 90 | 
            -
            as an array of string tokens, and defaults to ARGV | 
| 91 | 
            -
             | 
| 97 | 
            +
            as an array of string tokens, and defaults to +ARGV+. If the program is invoked using
         | 
| 98 | 
            +
            <tt>--help</tt>, Oyster will throw a <tt>Oyster::HelpRendered</tt> exception that you can
         | 
| 92 99 | 
             
            use to halt your program if necessary. An example taking input from the command
         | 
| 93 100 | 
             
            line:
         | 
| 94 101 |  | 
| @@ -105,6 +112,10 @@ as specified by the user. For example: | |
| 105 112 | 
             
              Input:    --no-recurse
         | 
| 106 113 | 
             
              Oupput:   opts[:recurse] == false
         | 
| 107 114 |  | 
| 115 | 
            +
              Input:    --all
         | 
| 116 | 
            +
              Output    options[:verbose] == true
         | 
| 117 | 
            +
                        options[:recurse] == true
         | 
| 118 | 
            +
              
         | 
| 108 119 | 
             
              Input:    --dest /path/to/mydir
         | 
| 109 120 | 
             
              Output:   opts[:dest] == '/path/to/mydir'
         | 
| 110 121 |  | 
| @@ -136,6 +147,7 @@ glob before handing it to the Ruby interpreter. | |
| 136 147 | 
             
                        -- Oyster will call Dir.glob('**/*.rb')
         | 
| 137 148 | 
             
                           opts[:files] == ['foo.rb', 'bar.rb', 'dir/baz.rb', ...]
         | 
| 138 149 |  | 
| 150 | 
            +
             | 
| 139 151 | 
             
            === Unclaimed input
         | 
| 140 152 |  | 
| 141 153 | 
             
            Any input tokens not absorbed by one of the option flags will be written to an
         | 
| @@ -146,6 +158,7 @@ array in <tt>opts[:unclaimed]</tt>: | |
| 146 158 | 
             
                        opts[:dest] == '/path/to/dir'
         | 
| 147 159 | 
             
                        opts[:unclaimed] == ['some_arg']
         | 
| 148 160 |  | 
| 161 | 
            +
             | 
| 149 162 | 
             
            === Subcommands
         | 
| 150 163 |  | 
| 151 164 | 
             
            You can easily create subcommands by nesting specs inside the main one:
         | 
| @@ -179,14 +192,6 @@ Subcommand options are stored as a hash inside the main options hash: | |
| 179 192 | 
             
            Beware that you cannot give a subcommand the same name as an option flag,
         | 
| 180 193 | 
             
            otherwise you'll get a name collision in the output.
         | 
| 181 194 |  | 
| 182 | 
            -
            === Requirements
         | 
| 183 | 
            -
             | 
| 184 | 
            -
            * Rubygems
         | 
| 185 | 
            -
            * Oyster gem
         | 
| 186 | 
            -
             | 
| 187 | 
            -
            === Installation
         | 
| 188 | 
            -
             | 
| 189 | 
            -
              sudo gem install oyster
         | 
| 190 195 |  | 
| 191 196 | 
             
            === License
         | 
| 192 197 |  | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/oyster.rb
    CHANGED
    
    | @@ -1,11 +1,14 @@ | |
| 1 1 | 
             
            module Oyster
         | 
| 2 | 
            -
              VERSION = '0.9. | 
| 2 | 
            +
              VERSION = '0.9.2'
         | 
| 3 3 |  | 
| 4 4 | 
             
              LONG_NAME   = /^--([a-z\[][a-z0-9\]\-]+)$/i
         | 
| 5 5 | 
             
              SHORT_NAME  = /^-([a-z0-9]+)$/i
         | 
| 6 6 |  | 
| 7 7 | 
             
              HELP_INDENT = 7
         | 
| 8 | 
            -
              HELP_WIDTH  =  | 
| 8 | 
            +
              HELP_WIDTH  = 80
         | 
| 9 | 
            +
              
         | 
| 10 | 
            +
              STOP_FLAG   = '--'
         | 
| 11 | 
            +
              NEGATOR     = /^no-/
         | 
| 9 12 |  | 
| 10 13 | 
             
              WINDOWS = RUBY_PLATFORM.split('-').any? { |part| part =~ /mswin\d*/i }
         | 
| 11 14 |  | 
| @@ -19,7 +22,7 @@ module Oyster | |
| 19 22 | 
             
              end
         | 
| 20 23 |  | 
| 21 24 | 
             
              def self.is_name?(string)
         | 
| 22 | 
            -
                !string.nil? and !!(string =~ LONG_NAME || string =~ SHORT_NAME || string ==  | 
| 25 | 
            +
                !string.nil? and !!(string =~ LONG_NAME || string =~ SHORT_NAME || string == STOP_FLAG)
         | 
| 23 26 | 
             
              end
         | 
| 24 27 | 
             
            end
         | 
| 25 28 |  | 
    
        data/lib/oyster/specification.rb
    CHANGED
    
    | @@ -49,7 +49,7 @@ module Oyster | |
| 49 49 | 
             
                  output = {:unclaimed => []}
         | 
| 50 50 |  | 
| 51 51 | 
             
                  while token = input.shift
         | 
| 52 | 
            -
                    if token ==  | 
| 52 | 
            +
                    if token == STOP_FLAG
         | 
| 53 53 | 
             
                      output[:unclaimed] = output[:unclaimed] + input
         | 
| 54 54 | 
             
                      break
         | 
| 55 55 | 
             
                    end
         | 
| @@ -61,8 +61,8 @@ module Oyster | |
| 61 61 |  | 
| 62 62 | 
             
                    input = short.scan(/./).map { |s| "-#{s}" } + input and next if short and short.size > 1
         | 
| 63 63 |  | 
| 64 | 
            -
                    negative = !!(long && long =~  | 
| 65 | 
            -
                    long.sub!( | 
| 64 | 
            +
                    negative = !!(long && long =~ NEGATOR)
         | 
| 65 | 
            +
                    long.sub!(NEGATOR, '') if negative
         | 
| 66 66 |  | 
| 67 67 | 
             
                    option ||= self[long] || self[short]
         | 
| 68 68 | 
             
                    output[:unclaimed] << token and next unless option
         | 
| @@ -95,34 +95,53 @@ module Oyster | |
| 95 95 | 
             
                  initial
         | 
| 96 96 | 
             
                end
         | 
| 97 97 |  | 
| 98 | 
            -
                def help
         | 
| 99 | 
            -
                   | 
| 100 | 
            -
                   | 
| 101 | 
            -
                   | 
| 102 | 
            -
                   | 
| 98 | 
            +
                def help(stream = $stdout)
         | 
| 99 | 
            +
                  render(stream, @data[:name],         1, 'NAME')
         | 
| 100 | 
            +
                  render(stream, @data[:synopsis],     1, 'SYNOPSIS', false, true)
         | 
| 101 | 
            +
                  render(stream, @data[:description],  1, 'DESCRIPTION')
         | 
| 102 | 
            +
                  
         | 
| 103 | 
            +
                  i = 0
         | 
| 104 | 
            +
                  stream.puts "\n#{ bold }OPTIONS#{ normal }"
         | 
| 103 105 | 
             
                  each do |option|
         | 
| 104 | 
            -
                     | 
| 105 | 
            -
                     | 
| 106 | 
            -
                     | 
| 106 | 
            +
                    render(stream, option.help_names.join(', '), 1, nil, false, true)
         | 
| 107 | 
            +
                    render(stream, option.description, 2)
         | 
| 108 | 
            +
                    i += 1
         | 
| 109 | 
            +
                    stream.puts "\n" if i < @options.size
         | 
| 107 110 | 
             
                  end
         | 
| 108 | 
            -
                   | 
| 109 | 
            -
                   | 
| 110 | 
            -
                   | 
| 111 | 
            +
                  
         | 
| 112 | 
            +
                  render(stream, @data[:notes],        1, 'NOTES')
         | 
| 113 | 
            +
                  render(stream, @data[:author],       1, 'AUTHOR')
         | 
| 114 | 
            +
                  render(stream, @data[:copyright],    1, 'COPYRIGHT')
         | 
| 115 | 
            +
                  stream.puts "\n"
         | 
| 111 116 | 
             
                  self
         | 
| 112 117 | 
             
                end
         | 
| 113 118 |  | 
| 114 | 
            -
                 | 
| 119 | 
            +
                # Plagiarised from Trollop, Copyright (c) 2008 William Morgan
         | 
| 120 | 
            +
                def display_width
         | 
| 121 | 
            +
                  @width ||= begin
         | 
| 122 | 
            +
                               require 'curses'
         | 
| 123 | 
            +
                               Curses.init_screen
         | 
| 124 | 
            +
                               x = Curses.cols
         | 
| 125 | 
            +
                               Curses.close_screen
         | 
| 126 | 
            +
                               x
         | 
| 127 | 
            +
                             rescue
         | 
| 128 | 
            +
                               HELP_WIDTH
         | 
| 129 | 
            +
                             end
         | 
| 130 | 
            +
                  @width - HELP_INDENT
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
                
         | 
| 133 | 
            +
                def render(stream, text, level = 1, title = nil, join = true, man = false)
         | 
| 115 134 | 
             
                  return unless text
         | 
| 116 | 
            -
                  puts "\n" + format("#{ bold }#{ title }#{ normal }", level - 1) if title
         | 
| 135 | 
            +
                  stream.puts "\n" + format("#{ normal }#{ bold }#{ title }#{ normal }", level - 1) if title
         | 
| 117 136 | 
             
                  text = man_format(text) if man
         | 
| 118 | 
            -
                  puts format(text, level, join)
         | 
| 137 | 
            +
                  stream.puts format(text, level, join)
         | 
| 119 138 | 
             
                end
         | 
| 120 139 |  | 
| 121 140 | 
             
                def format(text, level = 1, join = true)
         | 
| 122 141 | 
             
                  lines   = text.split(/\n/)
         | 
| 123 142 | 
             
                  outdent = lines.inject(1000) { |n,s| [s.scan(/^\s*/).first.size, n].min }
         | 
| 124 143 | 
             
                  indent  = level * HELP_INDENT
         | 
| 125 | 
            -
                  width   =  | 
| 144 | 
            +
                  width   = display_width - indent
         | 
| 126 145 |  | 
| 127 146 | 
             
                  lines.map { |line|
         | 
| 128 147 | 
             
                    line.sub(/\s*$/, '').sub(%r{^\s{#{outdent}}}, '')
         | 
    
        data/test/test_oyster.rb
    CHANGED
    
    | @@ -35,6 +35,13 @@ class OysterTest < Test::Unit::TestCase | |
| 35 35 | 
             
                  Which binary to use. You can change the executable used to format the output
         | 
| 36 36 | 
             
                  of this command, setting it to your scripting language of choice. This is just
         | 
| 37 37 | 
             
                  a lot of text to make sure help formatting works.
         | 
| 38 | 
            +
                  
         | 
| 39 | 
            +
                    class WeCan
         | 
| 40 | 
            +
                      attr_writer :write_code
         | 
| 41 | 
            +
                      
         | 
| 42 | 
            +
                      def in_option_descriptions
         | 
| 43 | 
            +
                      end
         | 
| 44 | 
            +
                    end
         | 
| 38 45 | 
             
                  EOS
         | 
| 39 46 |  | 
| 40 47 | 
             
                  integer :status,    :default => 200,
         | 
| @@ -188,7 +195,7 @@ class OysterTest < Test::Unit::TestCase | |
| 188 195 |  | 
| 189 196 | 
             
              def test_file
         | 
| 190 197 | 
             
                opts = @spec.parse %w(--path Rakefile)
         | 
| 191 | 
            -
                assert opts[:path] =~ / | 
| 198 | 
            +
                assert opts[:path] =~ /Hoe/
         | 
| 192 199 | 
             
              end
         | 
| 193 200 |  | 
| 194 201 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: oyster
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              version: 0.9. | 
| 4 | 
            +
              version: 0.9.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - James Coglan
         | 
| @@ -9,7 +9,7 @@ autorequire: | |
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 11 |  | 
| 12 | 
            -
            date: 2009- | 
| 12 | 
            +
            date: 2009-06-19 00:00:00 +01:00
         | 
| 13 13 | 
             
            default_executable: 
         | 
| 14 14 | 
             
            dependencies: 
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -20,9 +20,9 @@ dependencies: | |
| 20 20 | 
             
                requirements: 
         | 
| 21 21 | 
             
                - - ">="
         | 
| 22 22 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 23 | 
            -
                    version:  | 
| 23 | 
            +
                    version: 2.0.0
         | 
| 24 24 | 
             
                version: 
         | 
| 25 | 
            -
            description:  | 
| 25 | 
            +
            description: ""
         | 
| 26 26 | 
             
            email: 
         | 
| 27 27 | 
             
            - jcoglan@googlemail.com
         | 
| 28 28 | 
             
            executables: []
         | 
| @@ -41,18 +41,20 @@ files: | |
| 41 41 | 
             
            - lib/oyster.rb
         | 
| 42 42 | 
             
            - lib/oyster/specification.rb
         | 
| 43 43 | 
             
            - lib/oyster/option.rb
         | 
| 44 | 
            +
            - lib/oyster/options/array.rb
         | 
| 45 | 
            +
            - lib/oyster/options/file.rb
         | 
| 44 46 | 
             
            - lib/oyster/options/flag.rb
         | 
| 45 | 
            -
            - lib/oyster/options/string.rb
         | 
| 46 | 
            -
            - lib/oyster/options/integer.rb
         | 
| 47 47 | 
             
            - lib/oyster/options/float.rb
         | 
| 48 | 
            -
            - lib/oyster/options/file.rb
         | 
| 49 | 
            -
            - lib/oyster/options/array.rb
         | 
| 50 48 | 
             
            - lib/oyster/options/glob.rb
         | 
| 49 | 
            +
            - lib/oyster/options/integer.rb
         | 
| 51 50 | 
             
            - lib/oyster/options/shortcut.rb
         | 
| 51 | 
            +
            - lib/oyster/options/string.rb
         | 
| 52 52 | 
             
            - lib/oyster/options/subcommand.rb
         | 
| 53 53 | 
             
            - test/test_oyster.rb
         | 
| 54 54 | 
             
            has_rdoc: true
         | 
| 55 55 | 
             
            homepage: http://github.com/jcoglan/oyster
         | 
| 56 | 
            +
            licenses: []
         | 
| 57 | 
            +
             | 
| 56 58 | 
             
            post_install_message: 
         | 
| 57 59 | 
             
            rdoc_options: 
         | 
| 58 60 | 
             
            - --main
         | 
| @@ -74,9 +76,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 74 76 | 
             
            requirements: []
         | 
| 75 77 |  | 
| 76 78 | 
             
            rubyforge_project: oyster
         | 
| 77 | 
            -
            rubygems_version: 1.3. | 
| 79 | 
            +
            rubygems_version: 1.3.3
         | 
| 78 80 | 
             
            signing_key: 
         | 
| 79 | 
            -
            specification_version:  | 
| 80 | 
            -
            summary:  | 
| 81 | 
            +
            specification_version: 3
         | 
| 82 | 
            +
            summary: ""
         | 
| 81 83 | 
             
            test_files: 
         | 
| 82 84 | 
             
            - test/test_oyster.rb
         |