cuttlebone 0.1.3
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/.gitignore +6 -0
 - data/CHANGELOG.md +22 -0
 - data/Gemfile +2 -0
 - data/README.md +56 -0
 - data/Rakefile +55 -0
 - data/cuttlebone.gemspec +27 -0
 - data/examples/todo.rb +57 -0
 - data/features/example.feature +53 -0
 - data/features/step_definitions/steps.rb +76 -0
 - data/features/support/env.rb +2 -0
 - data/features/support/test_driver.rb +24 -0
 - data/features/switching_contexts.feature +78 -0
 - data/lib/cuttlebone.rb +19 -0
 - data/lib/cuttlebone/controller.rb +69 -0
 - data/lib/cuttlebone/definition.rb +58 -0
 - data/lib/cuttlebone/exceptions.rb +24 -0
 - data/lib/cuttlebone/session.rb +4 -0
 - data/lib/cuttlebone/session/base.rb +61 -0
 - data/lib/cuttlebone/session/rack.rb +4 -0
 - data/lib/cuttlebone/session/shell.rb +17 -0
 - data/lib/cuttlebone/version.rb +3 -0
 - data/spec/controller_spec.rb +79 -0
 - data/spec/cuttlebone_spec.rb +19 -0
 - data/spec/definition_spec.rb +100 -0
 - data/spec/rcov.opts +2 -0
 - data/spec/session_base_spec.rb +82 -0
 - data/spec/spec.opts +4 -0
 - data/spec/spec_helper.rb +8 -0
 - data/vendor/active_support.rb +56 -0
 - metadata +142 -0
 
    
        data/.gitignore
    ADDED
    
    
    
        data/CHANGELOG.md
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ## 0.1.2 / 2011-03-18
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            * Changed directory structure to look like a real gem. :)
         
     | 
| 
      
 4 
     | 
    
         
            +
            * Finalized initial test cases (spec/cucumber).
         
     | 
| 
      
 5 
     | 
    
         
            +
            * github.com release!
         
     | 
| 
      
 6 
     | 
    
         
            +
            * Added my original todo example using the new syntax.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            ## 0.1.1 / 2011-03-15
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            * Added new test cases and new "polished" features.
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ## 0.1.0 / 2010-07-06
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            * After a long (inactive) year, some projects generated a need to push
         
     | 
| 
      
 15 
     | 
    
         
            +
              cuttlebone a little further.  There are no new features but tests and
         
     | 
| 
      
 16 
     | 
    
         
            +
              documentation.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            ## 0.0.1 / 2009-05-13
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            * Birthday!  Presentation on the topic (and my proof of concept demo):
         
     | 
| 
      
 21 
     | 
    
         
            +
              http://www.viddler.com/explore/budapestrb/videos/4/
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # cuttlebone
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Cuttlebone helps you creating shell-alike applications.  Easily.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            ## INSTALL AND USAGE
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Install Ruby 1.9.2, clone, setup, try. :)  Check `examples` and `features`
         
     | 
| 
      
 8 
     | 
    
         
            +
            directories for examples.
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            ## TODO
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            * Documentation-documentation-documentation...
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            * Tests-tests-tests...
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            * Methods defined in context definitions should be called from command/prompt
         
     | 
| 
      
 17 
     | 
    
         
            +
              blocks.
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            * For Symbol contexts special attribute and method definitions should work
         
     | 
| 
      
 20 
     | 
    
         
            +
              intuitively.
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            * Terminal handling, colors, sizes (eg.
         
     | 
| 
      
 23 
     | 
    
         
            +
              http://codeidol.com/other/rubyckbk/User-Interface/Determining-Terminal-Size/,
         
     | 
| 
      
 24 
     | 
    
         
            +
              ncurses(?)).
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            * Autocomplete (eg. cldwalker/bond or with a new approach based on 1.9.2's
         
     | 
| 
      
 27 
     | 
    
         
            +
              readline enhancement).
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            * Asynchronous (server-initiated) output.
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            * Web driver.
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            ## LICENSE
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            (The MIT License)
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            Copyright (c) 2009-2011 Golda Bence <bence@golda.me>
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining
         
     | 
| 
      
 40 
     | 
    
         
            +
            a copy of this software and associated documentation files (the
         
     | 
| 
      
 41 
     | 
    
         
            +
            'Software'), to deal in the Software without restriction, including
         
     | 
| 
      
 42 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish,
         
     | 
| 
      
 43 
     | 
    
         
            +
            distribute, sublicense, and/or sell copies of the Software, and to
         
     | 
| 
      
 44 
     | 
    
         
            +
            permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 45 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 48 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 51 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
         
     | 
| 
      
 52 
     | 
    
         
            +
            MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
         
     | 
| 
      
 53 
     | 
    
         
            +
            IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
         
     | 
| 
      
 54 
     | 
    
         
            +
            CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
         
     | 
| 
      
 55 
     | 
    
         
            +
            TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
         
     | 
| 
      
 56 
     | 
    
         
            +
            SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,55 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'bundler/setup'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'rake'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'rake/rdoctask'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'rspec/core/rake_task'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'cucumber/rake/task'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            require 'rake/packagetask'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'rake/gempackagetask'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            CUTTLEBONE_GEMSPEC = eval(File.read(File.expand_path('../cuttlebone.gemspec', __FILE__)))
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            desc 'Default: run specs'
         
     | 
| 
      
 15 
     | 
    
         
            +
            task :default => 'spec'
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
            namespace :spec do
         
     | 
| 
      
 18 
     | 
    
         
            +
              desc 'Run all specs in spec directory (format=progress)'
         
     | 
| 
      
 19 
     | 
    
         
            +
              RSpec::Core::RakeTask.new(:progress) do |t|
         
     | 
| 
      
 20 
     | 
    
         
            +
                t.pattern = './spec/**/*_spec.rb'
         
     | 
| 
      
 21 
     | 
    
         
            +
                t.rspec_opts = ['--color', '--format=progress']
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              desc 'Run all specs in spec directory (format=documentation)'
         
     | 
| 
      
 25 
     | 
    
         
            +
              RSpec::Core::RakeTask.new(:documentation) do |t|
         
     | 
| 
      
 26 
     | 
    
         
            +
                t.pattern = './spec/**/*_spec.rb'
         
     | 
| 
      
 27 
     | 
    
         
            +
                t.rspec_opts = ['--color', '--format=documentation']
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              desc "Run specs with rcov"
         
     | 
| 
      
 31 
     | 
    
         
            +
              RSpec::Core::RakeTask.new(:rcov) do |t|
         
     | 
| 
      
 32 
     | 
    
         
            +
                t.pattern = './spec/**/*_spec.rb'
         
     | 
| 
      
 33 
     | 
    
         
            +
                t.rcov = true
         
     | 
| 
      
 34 
     | 
    
         
            +
                t.rcov_opts = ['--exclude', 'gems/,spec/,features/']
         
     | 
| 
      
 35 
     | 
    
         
            +
              end
         
     | 
| 
      
 36 
     | 
    
         
            +
            end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
            task :spec => 'spec:progress'
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            desc 'Run all cucumber tests.'
         
     | 
| 
      
 41 
     | 
    
         
            +
            Cucumber::Rake::Task.new do |t|
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            desc 'Generate documentation for the a4-core plugin.'
         
     | 
| 
      
 45 
     | 
    
         
            +
            Rake::RDocTask.new(:rdoc) do |rdoc|
         
     | 
| 
      
 46 
     | 
    
         
            +
              rdoc.rdoc_dir = 'rdoc'
         
     | 
| 
      
 47 
     | 
    
         
            +
              rdoc.title    = 'A4::Core'
         
     | 
| 
      
 48 
     | 
    
         
            +
              rdoc.options << '--line-numbers' << '--inline-source' << '--charset=UTF-8'
         
     | 
| 
      
 49 
     | 
    
         
            +
              rdoc.rdoc_files.include('README')
         
     | 
| 
      
 50 
     | 
    
         
            +
              rdoc.rdoc_files.include('lib/**/*.rb')
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            Rake::GemPackageTask.new(CUTTLEBONE_GEMSPEC) do |p|
         
     | 
| 
      
 54 
     | 
    
         
            +
              p.gem_spec = CUTTLEBONE_GEMSPEC
         
     | 
| 
      
 55 
     | 
    
         
            +
            end
         
     | 
    
        data/cuttlebone.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path("../lib/cuttlebone/version", __FILE__)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 4 
     | 
    
         
            +
              s.name        = "cuttlebone"
         
     | 
| 
      
 5 
     | 
    
         
            +
              s.version     = Cuttlebone::VERSION
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.platform    = Gem::Platform::RUBY
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.authors     = ["Bence Golda"]
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.email       = ["bence@golda.me"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.homepage    = "http://github.com/gbence/cuttlebone"
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.summary     = "cuttlebone-#{Cuttlebone::VERSION}"
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.description = "Cuttlebone helps you creating shell-alike applications."
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              s.rubyforge_project         = "cuttlebone"
         
     | 
| 
      
 14 
     | 
    
         
            +
              s.required_rubygems_version = ">= 1.3.7"
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              s.add_development_dependency "bundler",  "~> 1.0.0"
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.add_development_dependency "rspec",    "~> 2.5.0"
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.add_development_dependency "i18n"
         
     | 
| 
      
 19 
     | 
    
         
            +
              s.add_development_dependency "cucumber", "~> 0.10.0"
         
     | 
| 
      
 20 
     | 
    
         
            +
              s.add_development_dependency "rcov",     "~> 0.9.0"
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              s.files            = `git ls-files`.split("\n")
         
     | 
| 
      
 23 
     | 
    
         
            +
              s.executables      = `git ls-files`.split("\n").select{|f| f =~ /^bin/}
         
     | 
| 
      
 24 
     | 
    
         
            +
              s.extra_rdoc_files = [ "README.md" ]
         
     | 
| 
      
 25 
     | 
    
         
            +
              s.rdoc_options     = ["--charset=UTF-8"]
         
     | 
| 
      
 26 
     | 
    
         
            +
              s.require_path     = 'lib'
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/todo.rb
    ADDED
    
    | 
         @@ -0,0 +1,57 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/env ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require File.expand_path('../../lib/cuttlebone', __FILE__)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            ##
         
     | 
| 
      
 7 
     | 
    
         
            +
            # MODEL
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            class Task
         
     | 
| 
      
 10 
     | 
    
         
            +
              @@id = 0
         
     | 
| 
      
 11 
     | 
    
         
            +
              attr_accessor :id, :title
         
     | 
| 
      
 12 
     | 
    
         
            +
              def initialize options={}
         
     | 
| 
      
 13 
     | 
    
         
            +
                @id    = (@@id+=1)
         
     | 
| 
      
 14 
     | 
    
         
            +
                @title = options.delete(:title)
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            ##
         
     | 
| 
      
 19 
     | 
    
         
            +
            # CUTTLEBONE DESCRIPTIONS
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
            context Array do
         
     | 
| 
      
 22 
     | 
    
         
            +
              #def find_task_by_id(id_s)
         
     | 
| 
      
 23 
     | 
    
         
            +
              #  id = id_s.to_i
         
     | 
| 
      
 24 
     | 
    
         
            +
              #  detect { |t| t.id == id }
         
     | 
| 
      
 25 
     | 
    
         
            +
              #end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              prompt()    { "tasks(#{size})" }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
              command(?l) { each { |t| output('(%03d) %50s' % [t.id, t.title]) } }
         
     | 
| 
      
 30 
     | 
    
         
            +
              command(?n) { send(:<<, t = Task.new); add t }
         
     | 
| 
      
 31 
     | 
    
         
            +
              command /^([0-9]+)$/ do |id_s|
         
     | 
| 
      
 32 
     | 
    
         
            +
                #t = find_task_by_id(id_s)
         
     | 
| 
      
 33 
     | 
    
         
            +
                id = id_s.to_i
         
     | 
| 
      
 34 
     | 
    
         
            +
                t  = detect { |t| t.id == id }
         
     | 
| 
      
 35 
     | 
    
         
            +
                add(t) if t
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
              command /^d ([0-9]+)$/ do |id_s|
         
     | 
| 
      
 38 
     | 
    
         
            +
                #t = find_task_by_id(id_s)
         
     | 
| 
      
 39 
     | 
    
         
            +
                id = id_s.to_i
         
     | 
| 
      
 40 
     | 
    
         
            +
                t  = detect { |t| t.id == id }
         
     | 
| 
      
 41 
     | 
    
         
            +
                delete(t)
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
              command(?q) { drop }
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            context Task do
         
     | 
| 
      
 47 
     | 
    
         
            +
              prompt()    { ('%03d' % [id]) + (' ' + (title.size<=20 ? title : "#{title[0..18]}…") rescue '') }
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              command(?q) { drop }
         
     | 
| 
      
 50 
     | 
    
         
            +
              command /^(.+)$/ do |text|
         
     | 
| 
      
 51 
     | 
    
         
            +
                send(:title=, text)
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
            end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            at_exit do
         
     | 
| 
      
 56 
     | 
    
         
            +
              Cuttlebone.run([Task.new(:title => 'x'), Task.new(:title => 'y')])
         
     | 
| 
      
 57 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            @console @example
         
     | 
| 
      
 2 
     | 
    
         
            +
            Feature: a simple example
         
     | 
| 
      
 3 
     | 
    
         
            +
              In order to be able to manage a simple todo list
         
     | 
| 
      
 4 
     | 
    
         
            +
              As a programmer
         
     | 
| 
      
 5 
     | 
    
         
            +
              I want to create cuttlebone program
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              Scenario: starting with no defined contexts
         
     | 
| 
      
 8 
     | 
    
         
            +
                Given no cuttlebone code
         
     | 
| 
      
 9 
     | 
    
         
            +
                When I start an "x" session
         
     | 
| 
      
 10 
     | 
    
         
            +
                Then I should get an error
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              Scenario: starting with an existing context
         
     | 
| 
      
 13 
     | 
    
         
            +
                Given the following cuttlebone code:
         
     | 
| 
      
 14 
     | 
    
         
            +
                  """
         
     | 
| 
      
 15 
     | 
    
         
            +
                  context "x" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                  """
         
     | 
| 
      
 18 
     | 
    
         
            +
                When I start an "x" session
         
     | 
| 
      
 19 
     | 
    
         
            +
                Then I should see an empty prompt
         
     | 
| 
      
 20 
     | 
    
         
            +
                And I should be in context "x"
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              Scenario: starting with a missing context
         
     | 
| 
      
 23 
     | 
    
         
            +
                Given the following cuttlebone code:
         
     | 
| 
      
 24 
     | 
    
         
            +
                  """
         
     | 
| 
      
 25 
     | 
    
         
            +
                  context "x" do
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                  """
         
     | 
| 
      
 28 
     | 
    
         
            +
                When I start a "y" session
         
     | 
| 
      
 29 
     | 
    
         
            +
                Then I should get an error
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              Scenario: starting a context with prompt defined
         
     | 
| 
      
 32 
     | 
    
         
            +
                Given the following cuttlebone code:
         
     | 
| 
      
 33 
     | 
    
         
            +
                  """
         
     | 
| 
      
 34 
     | 
    
         
            +
                  context "x" do
         
     | 
| 
      
 35 
     | 
    
         
            +
                    prompt { "prompt" }
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  """
         
     | 
| 
      
 38 
     | 
    
         
            +
                When I start an "x" session
         
     | 
| 
      
 39 
     | 
    
         
            +
                Then I should see "prompt" as prompt
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              Scenario: invoking a simple command
         
     | 
| 
      
 42 
     | 
    
         
            +
                Given the following cuttlebone code:
         
     | 
| 
      
 43 
     | 
    
         
            +
                  """
         
     | 
| 
      
 44 
     | 
    
         
            +
                  context "x" do
         
     | 
| 
      
 45 
     | 
    
         
            +
                    command /^y$/ do
         
     | 
| 
      
 46 
     | 
    
         
            +
                      self
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
      
 49 
     | 
    
         
            +
                  """
         
     | 
| 
      
 50 
     | 
    
         
            +
                When I start an "x" session
         
     | 
| 
      
 51 
     | 
    
         
            +
                And I call command "y"
         
     | 
| 
      
 52 
     | 
    
         
            +
                Then I should see an empty prompt
         
     | 
| 
      
 53 
     | 
    
         
            +
                And I should be in context "x"
         
     | 
| 
         @@ -0,0 +1,76 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'pp'
         
     | 
| 
      
 2 
     | 
    
         
            +
            # schema / definitions
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            Given /^no cuttlebone code$/ do
         
     | 
| 
      
 5 
     | 
    
         
            +
              Cuttlebone.definitions.clear
         
     | 
| 
      
 6 
     | 
    
         
            +
            end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            Given /^the following cuttlebone code:$/ do |string|
         
     | 
| 
      
 9 
     | 
    
         
            +
              Given %{no cuttlebone code}
         
     | 
| 
      
 10 
     | 
    
         
            +
              Cuttlebone.instance_eval(string)
         
     | 
| 
      
 11 
     | 
    
         
            +
            end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            # initialization
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            Given /^a started "([^"]*)" session$/ do |objects|
         
     | 
| 
      
 16 
     | 
    
         
            +
              When %{I start a #{objects.inspect} session}
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            When /^I start (?:an? )?"([^"]*)" session$/ do |objects|
         
     | 
| 
      
 20 
     | 
    
         
            +
              @d = Cuttlebone::Session::Test.new(*(objects.scan(/([^,]{1,})(?:,\s*)?/).flatten))
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            # invocation
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            When /^I call command "([^"]*)"$/ do |command|
         
     | 
| 
      
 26 
     | 
    
         
            +
              @d.call(command)
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            # context related steps
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            Then /^I should be in context "([^"]*)"$/ do |name|
         
     | 
| 
      
 32 
     | 
    
         
            +
              @d.active_context.context.to_s.should == name
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            Then /^I should see a terminated session$/ do
         
     | 
| 
      
 36 
     | 
    
         
            +
              @d.should be_terminated
         
     | 
| 
      
 37 
     | 
    
         
            +
            end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
            Then /^I should be in the same context$/ do
         
     | 
| 
      
 40 
     | 
    
         
            +
              @d.previous_active_context.should == @d.active_context
         
     | 
| 
      
 41 
     | 
    
         
            +
            end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            Then /^I should not be in the same context$/ do
         
     | 
| 
      
 44 
     | 
    
         
            +
              @d.previous_active_context.should_not == @d.active_context
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            # output related steps
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            Then /^I should see "([^"]*)"$/ do |text|
         
     | 
| 
      
 50 
     | 
    
         
            +
              @d.output.should include(text)
         
     | 
| 
      
 51 
     | 
    
         
            +
            end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            # prompt related steps
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
            Then /^I should see "([^"]*)" as prompt$/ do |text|
         
     | 
| 
      
 56 
     | 
    
         
            +
              @d.prompt.should include(text)
         
     | 
| 
      
 57 
     | 
    
         
            +
            end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            Then /^I should see \/([^\/]*)\/ as prompt$/ do |regexp|
         
     | 
| 
      
 60 
     | 
    
         
            +
              @d.prompt.should match(regexp)
         
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
| 
      
 62 
     | 
    
         
            +
             
     | 
| 
      
 63 
     | 
    
         
            +
            Then /^I should see an empty prompt$/ do
         
     | 
| 
      
 64 
     | 
    
         
            +
              @d.prompt.should be_empty
         
     | 
| 
      
 65 
     | 
    
         
            +
            end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            # error related steps
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            Then /^I should see an error$/ do
         
     | 
| 
      
 70 
     | 
    
         
            +
              @d.error.should_not be_blank
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
            Then /^I should get an error$/ do
         
     | 
| 
      
 74 
     | 
    
         
            +
              @d.internal_error.should_not be_blank
         
     | 
| 
      
 75 
     | 
    
         
            +
            end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Cuttlebone::Session::Test < Cuttlebone::Session::Base
         
     | 
| 
      
 2 
     | 
    
         
            +
              def initialize *args
         
     | 
| 
      
 3 
     | 
    
         
            +
                super
         
     | 
| 
      
 4 
     | 
    
         
            +
                stack = []
         
     | 
| 
      
 5 
     | 
    
         
            +
                @stack.each { |c| stack << c }
         
     | 
| 
      
 6 
     | 
    
         
            +
                @stack_history = [ stack ]
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def process command
         
     | 
| 
      
 10 
     | 
    
         
            +
                stack = []
         
     | 
| 
      
 11 
     | 
    
         
            +
                @stack.each { |c| stack << c }
         
     | 
| 
      
 12 
     | 
    
         
            +
                @stack_history << stack
         
     | 
| 
      
 13 
     | 
    
         
            +
                a, n, o, e = super(command)
         
     | 
| 
      
 14 
     | 
    
         
            +
                @output = o
         
     | 
| 
      
 15 
     | 
    
         
            +
                @error  = e
         
     | 
| 
      
 16 
     | 
    
         
            +
                [ a, n, o, e ]
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              attr_reader :output, :error
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              def previous_active_context
         
     | 
| 
      
 22 
     | 
    
         
            +
                @stack_history[-2].last
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,78 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Feature: switching between contexts
         
     | 
| 
      
 2 
     | 
    
         
            +
              In order to be able to manage my todo list
         
     | 
| 
      
 3 
     | 
    
         
            +
              As a programmer
         
     | 
| 
      
 4 
     | 
    
         
            +
              I want to switch between cuttlebone contexts
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              Background:
         
     | 
| 
      
 7 
     | 
    
         
            +
                Given the following cuttlebone code:
         
     | 
| 
      
 8 
     | 
    
         
            +
                  """
         
     | 
| 
      
 9 
     | 
    
         
            +
                  context 'x' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                    command 'q' do
         
     | 
| 
      
 11 
     | 
    
         
            +
                      drop
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
                    command 'y' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                      replace 'y'
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                    command 'yy' do
         
     | 
| 
      
 17 
     | 
    
         
            +
                      add 'y'
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    command 'x' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                      self
         
     | 
| 
      
 21 
     | 
    
         
            +
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                    command 'xx' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                      add 'x'
         
     | 
| 
      
 24 
     | 
    
         
            +
                    end
         
     | 
| 
      
 25 
     | 
    
         
            +
                    command 'r' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                      replace 'x'
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                  context 'y' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                    command 'q' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                      drop
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                    command 'y' do
         
     | 
| 
      
 35 
     | 
    
         
            +
                      self
         
     | 
| 
      
 36 
     | 
    
         
            +
                    end
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                  """
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
              Scenario: quitting
         
     | 
| 
      
 41 
     | 
    
         
            +
                Given a started "x" session
         
     | 
| 
      
 42 
     | 
    
         
            +
                When I call command "q"
         
     | 
| 
      
 43 
     | 
    
         
            +
                Then I should see a terminated session
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              Scenario: replacing current context
         
     | 
| 
      
 46 
     | 
    
         
            +
                Given a started "x" session
         
     | 
| 
      
 47 
     | 
    
         
            +
                When I call command "y"
         
     | 
| 
      
 48 
     | 
    
         
            +
                Then I should be in context "y"
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              Scenario: returning the same context
         
     | 
| 
      
 51 
     | 
    
         
            +
                Given a started "x" session
         
     | 
| 
      
 52 
     | 
    
         
            +
                When I call command "x"
         
     | 
| 
      
 53 
     | 
    
         
            +
                Then I should be in the same context
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              Scenario: replacing with a similar context
         
     | 
| 
      
 56 
     | 
    
         
            +
                Given a started "x" session
         
     | 
| 
      
 57 
     | 
    
         
            +
                When I call command "r"
         
     | 
| 
      
 58 
     | 
    
         
            +
                Then I should not be in the same context
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
              Scenario: entering into a new context
         
     | 
| 
      
 61 
     | 
    
         
            +
                Given a started "x" session
         
     | 
| 
      
 62 
     | 
    
         
            +
                When I call command "yy"
         
     | 
| 
      
 63 
     | 
    
         
            +
                Then I should be in context "y"
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
              Scenario: dropping previously built context
         
     | 
| 
      
 66 
     | 
    
         
            +
                Given a started "x" session
         
     | 
| 
      
 67 
     | 
    
         
            +
                When I call command "yy"
         
     | 
| 
      
 68 
     | 
    
         
            +
                And I call command "q"
         
     | 
| 
      
 69 
     | 
    
         
            +
                Then I should be in context "x"
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              Scenario: consume multiple contexts and quit
         
     | 
| 
      
 72 
     | 
    
         
            +
                Given a started "x,y,y,x" session
         
     | 
| 
      
 73 
     | 
    
         
            +
                When I call command "q"
         
     | 
| 
      
 74 
     | 
    
         
            +
                And I call command "q"
         
     | 
| 
      
 75 
     | 
    
         
            +
                And I call command "q"
         
     | 
| 
      
 76 
     | 
    
         
            +
                Then I should be in context "x"
         
     | 
| 
      
 77 
     | 
    
         
            +
                When I call command "q"
         
     | 
| 
      
 78 
     | 
    
         
            +
                Then I should see a terminated session
         
     | 
    
        data/lib/cuttlebone.rb
    ADDED
    
    | 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            $: << File.expand_path('../', __FILE__)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require File.expand_path('../../vendor/active_support.rb', __FILE__)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module Cuttlebone
         
     | 
| 
      
 6 
     | 
    
         
            +
              require               'cuttlebone/exceptions'
         
     | 
| 
      
 7 
     | 
    
         
            +
              autoload :Controller, 'cuttlebone/controller'
         
     | 
| 
      
 8 
     | 
    
         
            +
              autoload :Definition, 'cuttlebone/definition'
         
     | 
| 
      
 9 
     | 
    
         
            +
              autoload :Session,    'cuttlebone/session'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              @@definitions = []
         
     | 
| 
      
 12 
     | 
    
         
            +
              def self.definitions; @@definitions; end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def self.run starting_objects, default_driver=Session::Shell
         
     | 
| 
      
 15 
     | 
    
         
            +
                default_driver.new(starting_objects).run
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            include Cuttlebone::Definition::DSL
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #
         
     | 
| 
      
 2 
     | 
    
         
            +
            # NOTE: we don't really want to pollute this proxy with a lot of private
         
     | 
| 
      
 3 
     | 
    
         
            +
            # (internal) methods to leave space for <<context>>'s real methods.
         
     | 
| 
      
 4 
     | 
    
         
            +
            class Cuttlebone::Controller
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              attr_reader :session, :context, :definition
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              def initialize session, context
         
     | 
| 
      
 9 
     | 
    
         
            +
                @session    = session
         
     | 
| 
      
 10 
     | 
    
         
            +
                @context    = context
         
     | 
| 
      
 11 
     | 
    
         
            +
                @definition = Cuttlebone.definitions.find { |d| d.match(context) }
         
     | 
| 
      
 12 
     | 
    
         
            +
                raise Cuttlebone::InvalidContextError, context, "No definiton was found for #{context.inspect}!" unless @definition
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              ##
         
     | 
| 
      
 16 
     | 
    
         
            +
              # Processes a command on its context's domain.
         
     | 
| 
      
 17 
     | 
    
         
            +
              #
         
     | 
| 
      
 18 
     | 
    
         
            +
              def process command
         
     | 
| 
      
 19 
     | 
    
         
            +
                @next_action = nil
         
     | 
| 
      
 20 
     | 
    
         
            +
                @output = []
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                return([:self, self, [], nil]) if command.empty?
         
     | 
| 
      
 23 
     | 
    
         
            +
                block, arguments = definition.proc_for(command)
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                instance_exec(*arguments, &block)
         
     | 
| 
      
 26 
     | 
    
         
            +
                action, context = @next_action || [ :self, self ]
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                return([ action, context, @output, nil ])
         
     | 
| 
      
 29 
     | 
    
         
            +
              rescue Cuttlebone::DoubleActionError
         
     | 
| 
      
 30 
     | 
    
         
            +
                raise
         
     | 
| 
      
 31 
     | 
    
         
            +
              rescue => e
         
     | 
| 
      
 32 
     | 
    
         
            +
                return([ :self, self, [], %{Cuttlebone::Controller: #{e.message} (#{e.class})} ])
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def prompt
         
     | 
| 
      
 36 
     | 
    
         
            +
                return(instance_exec(&@definition.prompt) || '')
         
     | 
| 
      
 37 
     | 
    
         
            +
              rescue => e
         
     | 
| 
      
 38 
     | 
    
         
            +
                %{error: #{e.message} (#{e.class.name})}
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              def drop
         
     | 
| 
      
 42 
     | 
    
         
            +
                __save_next_action! :drop
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              def add context
         
     | 
| 
      
 46 
     | 
    
         
            +
                __save_next_action! :add, context
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
              def replace context
         
     | 
| 
      
 50 
     | 
    
         
            +
                __save_next_action! :replace, context
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              def output text
         
     | 
| 
      
 54 
     | 
    
         
            +
                @output << text
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              def method_missing method_name, *args, &block
         
     | 
| 
      
 58 
     | 
    
         
            +
                return(@context.send(method_name, *args, &block)) if @context.respond_to?(method_name)
         
     | 
| 
      
 59 
     | 
    
         
            +
                return(super)
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
              private
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              def __save_next_action! action, context=nil
         
     | 
| 
      
 65 
     | 
    
         
            +
                raise Cuttlebone::DoubleActionError if @next_action
         
     | 
| 
      
 66 
     | 
    
         
            +
                @next_action = [ action, context ]
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,58 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Cuttlebone
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Definition
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                module DSL
         
     | 
| 
      
 5 
     | 
    
         
            +
                  def context object, options={}, &definition
         
     | 
| 
      
 6 
     | 
    
         
            +
                    Cuttlebone.definitions << Definition.new(object, options, &definition)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  end
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                class Parser
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def initialize definition
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @definition = definition
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def command string_or_regexp, &block
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @definition.commands << [ string_or_regexp, block, @last_description ]
         
     | 
| 
      
 17 
     | 
    
         
            +
                    @last_description = nil
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def description text
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @last_description = text
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def prompt text='', &block
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @definition.prompt = block_given? ? block : proc { text }
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                attr_accessor :prompt, :commands
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                def initialize object_or_class, options={}, &definition
         
     | 
| 
      
 34 
     | 
    
         
            +
                  raise ArgumentError, 'missing block' unless block_given?
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @object_or_class = object_or_class
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @options         = options
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @commands        = [] #Array.new(proc { |c| [:self, c, '', nil] })
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @prompt          = proc { |c| '' }
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  @parser = Parser.new(self)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @parser.instance_eval(&definition)
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                delegate :command, :to => '@parser'
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def match object
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @object_or_class === object
         
     | 
| 
      
 48 
     | 
    
         
            +
                  # TODO :if :unless options
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                def proc_for command
         
     | 
| 
      
 52 
     | 
    
         
            +
                  string_or_regexp, block, description = commands.find { |(sr,b,d)| sr === command } || raise(UnknownCommandError, "Unknown command: #{command.inspect}!")
         
     | 
| 
      
 53 
     | 
    
         
            +
                  return([ block, $~.captures ]) if $~
         
     | 
| 
      
 54 
     | 
    
         
            +
                  return([ block, [] ])
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
              end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Cuttlebone
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              ##
         
     | 
| 
      
 4 
     | 
    
         
            +
              # Raised when Controller is invoked with an invalid (not matching) context.
         
     | 
| 
      
 5 
     | 
    
         
            +
              # 
         
     | 
| 
      
 6 
     | 
    
         
            +
              class InvalidContextError < StandardError
         
     | 
| 
      
 7 
     | 
    
         
            +
                attr_reader :context
         
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize context, *args, &block
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @context = context
         
     | 
| 
      
 10 
     | 
    
         
            +
                  super *args, &block
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              ##
         
     | 
| 
      
 15 
     | 
    
         
            +
              # Raised on unknown command calls.
         
     | 
| 
      
 16 
     | 
    
         
            +
              #
         
     | 
| 
      
 17 
     | 
    
         
            +
              class UnknownCommandError < StandardError; end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              ##
         
     | 
| 
      
 20 
     | 
    
         
            +
              # Raised when multiple actions are invoked simultanously.
         
     | 
| 
      
 21 
     | 
    
         
            +
              #
         
     | 
| 
      
 22 
     | 
    
         
            +
              class DoubleActionError < StandardError; end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,61 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class Cuttlebone::Session::Base
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              attr_reader :stack, :internal_error
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              def initialize *stack_objects
         
     | 
| 
      
 6 
     | 
    
         
            +
                setup_contexts 'cuttlebone.stack_objects' => stack_objects
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              def active_context
         
     | 
| 
      
 10 
     | 
    
         
            +
                stack.last
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              delegate :name, :prompt, :to => :active_context
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              def setup_contexts env={}
         
     | 
| 
      
 16 
     | 
    
         
            +
                @stack ||= (env['cuttlebone.stack_objects'] || []).map{ |o| Cuttlebone::Controller.new(self, o) }
         
     | 
| 
      
 17 
     | 
    
         
            +
              rescue Cuttlebone::InvalidContextError => e
         
     | 
| 
      
 18 
     | 
    
         
            +
                @internal_error = %{Context initialization failed for #{e.context.inspect}!}
         
     | 
| 
      
 19 
     | 
    
         
            +
                @stack = []
         
     | 
| 
      
 20 
     | 
    
         
            +
              rescue => e
         
     | 
| 
      
 21 
     | 
    
         
            +
                @internal_error = %{Internal error occured: #{e.message} (#{e.class})}
         
     | 
| 
      
 22 
     | 
    
         
            +
                @stack = []
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
              private :setup_contexts
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              def process command
         
     | 
| 
      
 27 
     | 
    
         
            +
                active_context = @stack.pop
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                action, next_context, output, error = begin
         
     | 
| 
      
 30 
     | 
    
         
            +
                                                        a, n, o, e = active_context.process(command)
         
     | 
| 
      
 31 
     | 
    
         
            +
                                                        raise ArgumentError, "Unknown action: #{a}" unless [ :self, :replace, :add, :drop ].include?(a.to_s.to_sym)
         
     | 
| 
      
 32 
     | 
    
         
            +
                                                        raise TypeError, "Output must be an instance of String or nil!" unless o.is_a?(Array) or o.nil?
         
     | 
| 
      
 33 
     | 
    
         
            +
                                                        raise TypeError, "Error must be an instance of String or nil!" unless e.is_a?(String) or e.nil?
         
     | 
| 
      
 34 
     | 
    
         
            +
                                                        [ a.to_s.to_sym, n, o, e ]
         
     | 
| 
      
 35 
     | 
    
         
            +
                                                      rescue => e
         
     | 
| 
      
 36 
     | 
    
         
            +
                                                        [ :self, active_context, nil, %{Cuttlebone::Session: #{e.message} (#{e.class})} ]
         
     | 
| 
      
 37 
     | 
    
         
            +
                                                      end
         
     | 
| 
      
 38 
     | 
    
         
            +
                case action
         
     | 
| 
      
 39 
     | 
    
         
            +
                when :self
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @stack << active_context
         
     | 
| 
      
 41 
     | 
    
         
            +
                when :replace
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @stack << Cuttlebone::Controller.new(self, next_context)
         
     | 
| 
      
 43 
     | 
    
         
            +
                when :add
         
     | 
| 
      
 44 
     | 
    
         
            +
                  @stack << active_context << Cuttlebone::Controller.new(self, next_context)
         
     | 
| 
      
 45 
     | 
    
         
            +
                when :drop
         
     | 
| 
      
 46 
     | 
    
         
            +
                  # noop
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
                [ action, next_context, output, error ]
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
              private :process
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              def call command, env={}
         
     | 
| 
      
 53 
     | 
    
         
            +
                setup_contexts env
         
     | 
| 
      
 54 
     | 
    
         
            +
                process command
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
              def terminated?
         
     | 
| 
      
 58 
     | 
    
         
            +
                stack.empty?
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # TODO FIXME load readline iff it was invoked through command line interface
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'readline'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            class Cuttlebone::Session::Shell < Cuttlebone::Session::Base
         
     | 
| 
      
 5 
     | 
    
         
            +
              def run
         
     | 
| 
      
 6 
     | 
    
         
            +
                loop do
         
     | 
| 
      
 7 
     | 
    
         
            +
                  break if terminated?
         
     | 
| 
      
 8 
     | 
    
         
            +
                  command = Readline::readline("#{prompt} > ")
         
     | 
| 
      
 9 
     | 
    
         
            +
                  break unless command
         
     | 
| 
      
 10 
     | 
    
         
            +
                  Readline::HISTORY.push(command)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  _, _, output, error = call(command)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  print (output<<'').join("\n")
         
     | 
| 
      
 13 
     | 
    
         
            +
                  print "\033[01;31m#{error}\033[00m\n" if error
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,79 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Cuttlebone::Controller do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:valid_session) { mock("Cuttlebone::Session::Base") }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:valid_context) { 'x' }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              let(:drop_proc)    { proc { |*args| output 'dropped'; drop } }
         
     | 
| 
      
 8 
     | 
    
         
            +
              let(:self_proc)    { proc { |*args| output 'noop'; self } }
         
     | 
| 
      
 9 
     | 
    
         
            +
              let(:add_proc)     { proc { |*args| output 'added'; add 'x' } } # TODO FIXME change 'x' => valid_context somehow 'cause they are the same instance
         
     | 
| 
      
 10 
     | 
    
         
            +
              let(:replace_proc) { proc { |*args| output 'replaced'; replace 'x' } }
         
     | 
| 
      
 11 
     | 
    
         
            +
              let(:double_action_error_proc) { proc { |*args| output 'double action error'; drop; add 'x' } }
         
     | 
| 
      
 12 
     | 
    
         
            +
              let(:prompt_proc)  { proc { |*args| 'prompt' } }
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              let(:valid_context_definition) do
         
     | 
| 
      
 15 
     | 
    
         
            +
                x = mock('Cuttlebone::Definition "x"')
         
     | 
| 
      
 16 
     | 
    
         
            +
                x.stub!(:match).and_return() { |*args| args == [valid_context] }
         
     | 
| 
      
 17 
     | 
    
         
            +
                x.stub!(:proc_for).with('drop').and_return(drop_proc)
         
     | 
| 
      
 18 
     | 
    
         
            +
                x.stub!(:proc_for).with('self').and_return(self_proc)
         
     | 
| 
      
 19 
     | 
    
         
            +
                x.stub!(:proc_for).with('add').and_return(add_proc)
         
     | 
| 
      
 20 
     | 
    
         
            +
                x.stub!(:proc_for).with('replace').and_return(replace_proc)
         
     | 
| 
      
 21 
     | 
    
         
            +
                x.stub!(:proc_for).with('double').and_return(double_action_error_proc)
         
     | 
| 
      
 22 
     | 
    
         
            +
                x.stub!(:prompt).and_return(prompt_proc)
         
     | 
| 
      
 23 
     | 
    
         
            +
                x
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              before :each do
         
     | 
| 
      
 27 
     | 
    
         
            +
                Cuttlebone.stub!(:definitions).and_return([ valid_context_definition ])
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              context "given a valid context" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                subject { Cuttlebone::Controller.new(valid_session, valid_context) }
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                it "should return context object" do
         
     | 
| 
      
 34 
     | 
    
         
            +
                  subject.context.should == valid_context
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                it "should return [:self, self, nil, nil] to empty commands" do
         
     | 
| 
      
 38 
     | 
    
         
            +
                  subject.process('').should == [ :self, subject, [], nil ]
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                it "should return [:drop, nil, 'dropped', nil] to 'drop' commands" do
         
     | 
| 
      
 42 
     | 
    
         
            +
                  subject.process('drop').should == [:drop, nil, ['dropped'], nil]
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                it "should return [:self, self, 'noop', nil] to 'drop' commands" do
         
     | 
| 
      
 46 
     | 
    
         
            +
                  subject.process('self').should == [:self, subject, ['noop'], nil]
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                it "should return [:add, valid_context, 'added', nil] to 'drop' commands" do
         
     | 
| 
      
 50 
     | 
    
         
            +
                  subject.process('add').should == [:add, valid_context, ['added'], nil]
         
     | 
| 
      
 51 
     | 
    
         
            +
                end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                it "should return [:replace, valid_context, 'replaced', nil] to 'drop' commands" do
         
     | 
| 
      
 54 
     | 
    
         
            +
                  subject.process('replace').should == [:replace, valid_context, ['replaced'], nil]
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                it "should raise error on double action commands" do
         
     | 
| 
      
 58 
     | 
    
         
            +
                  expect{ subject.process('double') }.should raise_error(Cuttlebone::DoubleActionError)
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                it "should execute command in <<context>>'s context" do
         
     | 
| 
      
 62 
     | 
    
         
            +
                  valid_context_definition.stub!(:proc_for).with('x').and_return(proc{ x })
         
     | 
| 
      
 63 
     | 
    
         
            +
                  valid_context.should_receive(:x)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  subject.process('x')
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                it "should execute prompt in <<context>>'s context" do
         
     | 
| 
      
 68 
     | 
    
         
            +
                  valid_context_definition.stub!(:prompt).and_return(proc{ x })
         
     | 
| 
      
 69 
     | 
    
         
            +
                  valid_context.should_receive(:x)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  subject.prompt()
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
              context "given an invalid context" do
         
     | 
| 
      
 75 
     | 
    
         
            +
                it "should raise an exception" do
         
     | 
| 
      
 76 
     | 
    
         
            +
                  expect{ Cuttlebone::Controller.new(valid_session, 'invalid_context') }.should raise_error(Cuttlebone::InvalidContextError)
         
     | 
| 
      
 77 
     | 
    
         
            +
                end
         
     | 
| 
      
 78 
     | 
    
         
            +
              end
         
     | 
| 
      
 79 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Cuttlebone do
         
     | 
| 
      
 4 
     | 
    
         
            +
              before :each do
         
     | 
| 
      
 5 
     | 
    
         
            +
                Cuttlebone.definitions.clear
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              it "should start with no contexts defined" do
         
     | 
| 
      
 9 
     | 
    
         
            +
                Cuttlebone.definitions.should be_empty
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              it "should be able to evaluate new context definitions" do
         
     | 
| 
      
 13 
     | 
    
         
            +
                Cuttlebone.should respond_to(:context)
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              it "should start a new session" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                Cuttlebone.should respond_to(:run)
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,100 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path(File.join(File.dirname(__FILE__), '/spec_helper'))
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Cuttlebone::Definition do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:valid_context_identifier) { :c }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:valid_options)            { {} }
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:valid_block)              { proc { command('x') {} } }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              context "given valid but meaningless parameters" do
         
     | 
| 
      
 9 
     | 
    
         
            +
                subject { Cuttlebone::Definition.new(valid_context_identifier, valid_options, &valid_block) }
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                it "should match to the context id given" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                  subject.should match(valid_context_identifier)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                it "should return prompt" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                  subject.should respond_to(:prompt)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  subject.prompt.should be_a(Proc)
         
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              context "given class for context matcher" do
         
     | 
| 
      
 22 
     | 
    
         
            +
                let(:klass)     { Class.new(Object) }
         
     | 
| 
      
 23 
     | 
    
         
            +
                let(:instance1) { klass.new }
         
     | 
| 
      
 24 
     | 
    
         
            +
                let(:instance2) { klass.new }
         
     | 
| 
      
 25 
     | 
    
         
            +
                let(:other_instance) { Object.new }
         
     | 
| 
      
 26 
     | 
    
         
            +
                let(:subclass)  { Class.new(klass) }
         
     | 
| 
      
 27 
     | 
    
         
            +
                let(:instance3) { subclass.new }
         
     | 
| 
      
 28 
     | 
    
         
            +
                subject { Cuttlebone::Definition.new(klass, valid_options, &valid_block) }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                it "should match instances" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                  subject.should match(instance1)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  subject.should match(instance2)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  subject.should_not match(other_instance)
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                it "should match subclass instances" do
         
     | 
| 
      
 37 
     | 
    
         
            +
                  subject.should match(instance3)
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              context "given several commands" do
         
     | 
| 
      
 42 
     | 
    
         
            +
                let(:drop_block) { proc { drop } }
         
     | 
| 
      
 43 
     | 
    
         
            +
                let(:add_block)  { proc { |arg| add arg.to_s.to_sym } }
         
     | 
| 
      
 44 
     | 
    
         
            +
                let(:definition_with_several_commands) do
         
     | 
| 
      
 45 
     | 
    
         
            +
                  proc do
         
     | 
| 
      
 46 
     | 
    
         
            +
                    command 'nil_will_be_self' do
         
     | 
| 
      
 47 
     | 
    
         
            +
                    end
         
     | 
| 
      
 48 
     | 
    
         
            +
                    command 'drop' do
         
     | 
| 
      
 49 
     | 
    
         
            +
                      drop
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                    command 'add x' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                      add 0
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
                    command 'replace x' do
         
     | 
| 
      
 55 
     | 
    
         
            +
                      replace :x
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                    command 'self' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                      self
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
                    command 'double_action_error' do
         
     | 
| 
      
 61 
     | 
    
         
            +
                      add :x
         
     | 
| 
      
 62 
     | 
    
         
            +
                      drop
         
     | 
| 
      
 63 
     | 
    
         
            +
                    end
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                subject { Cuttlebone::Definition.new(valid_context_identifier, valid_options, &definition_with_several_commands) }
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                it "should have several commands" do
         
     | 
| 
      
 70 
     | 
    
         
            +
                  subject.should have(6).commands
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                it "should parse new commands" do
         
     | 
| 
      
 74 
     | 
    
         
            +
                  subject.command(/new command/) { self }
         
     | 
| 
      
 75 
     | 
    
         
            +
                  subject.should have(7).commands
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                it "should return the specific block for a command" do
         
     | 
| 
      
 79 
     | 
    
         
            +
                  subject.command /^add (.)$/, &add_block
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  subject.proc_for('add x').should_not == [add_block, []]
         
     | 
| 
      
 82 
     | 
    
         
            +
                  subject.proc_for('add y').should == [add_block, ['y']]
         
     | 
| 
      
 83 
     | 
    
         
            +
                end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                it "should parse arguments properly" do
         
     | 
| 
      
 86 
     | 
    
         
            +
                  subject.command /^add (.)(.)?$/, &(proc{|a,b|})
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  subject.proc_for('add y').last.should == ['y', nil]
         
     | 
| 
      
 89 
     | 
    
         
            +
                  subject.proc_for('add yz').last.should == ['y', 'z']
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                it "should return an error for unmatched commands" do
         
     | 
| 
      
 93 
     | 
    
         
            +
                  expect{ subject.proc_for('unmatched') }.should raise_error(Cuttlebone::UnknownCommandError)
         
     | 
| 
      
 94 
     | 
    
         
            +
                end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                it "should return no error on semantically wrong commands" do
         
     | 
| 
      
 97 
     | 
    
         
            +
                  expect{ subject.proc_for('double_action_error') }.should_not raise_error
         
     | 
| 
      
 98 
     | 
    
         
            +
                end
         
     | 
| 
      
 99 
     | 
    
         
            +
              end
         
     | 
| 
      
 100 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/rcov.opts
    ADDED
    
    
| 
         @@ -0,0 +1,82 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Cuttlebone::Session::Base do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:valid_context) { 'x' }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:valid_command) { 'y' }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              let(:valid_context_definition) do
         
     | 
| 
      
 8 
     | 
    
         
            +
                x = mock('Definition:x')
         
     | 
| 
      
 9 
     | 
    
         
            +
                x.stub!(:match).and_return() { |*args| args == [valid_context] }
         
     | 
| 
      
 10 
     | 
    
         
            +
                x.stub!(:proc_for).with(any_args()).and_return([proc{}, []])
         
     | 
| 
      
 11 
     | 
    
         
            +
                x
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              before :each do
         
     | 
| 
      
 15 
     | 
    
         
            +
                Cuttlebone.stub!(:definitions).and_return([ valid_context_definition ])
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              context "having an active 'x' context" do
         
     | 
| 
      
 19 
     | 
    
         
            +
                subject { Cuttlebone::Session::Base.new(valid_context) }
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                it { should_not be_terminated }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                it "should have no internal error" do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  subject.internal_error.should be_blank
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                it "should evaluate a string command" do
         
     | 
| 
      
 28 
     | 
    
         
            +
                  valid_context_definition.should_receive(:match).with(valid_context).and_return(true)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  subject.call(valid_command)
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                it "should return active context" do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  subject.should respond_to(:active_context)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  subject.active_context.should be_a(Cuttlebone::Controller)
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                it "should return with a [action, context, output, error] quadruple" do
         
     | 
| 
      
 38 
     | 
    
         
            +
                  a, c, o, e = subject.call(valid_context)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  [ :drop, :replace, :self, :add ].should include(a)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  o and o.should be_a(Array)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  e and e.should be_a(String)
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              context "having no active contexts" do
         
     | 
| 
      
 46 
     | 
    
         
            +
                subject { Cuttlebone::Session::Base.new() }
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                it "should have no internal error" do
         
     | 
| 
      
 49 
     | 
    
         
            +
                  subject.internal_error.should be_blank
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                it { should be_terminated }
         
     | 
| 
      
 53 
     | 
    
         
            +
              end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              context "having 1 context" do
         
     | 
| 
      
 56 
     | 
    
         
            +
                subject { Cuttlebone::Session::Base.new(valid_context) }
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                it "should have no internal error" do
         
     | 
| 
      
 59 
     | 
    
         
            +
                  subject.internal_error.should be_blank
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                it { should_not be_terminated }
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                it "should be terminated after a 'drop'" do
         
     | 
| 
      
 65 
     | 
    
         
            +
                  valid_context_definition.should_receive(:proc_for).with('drop').and_return([proc{drop}, []])
         
     | 
| 
      
 66 
     | 
    
         
            +
                  subject.call('drop')
         
     | 
| 
      
 67 
     | 
    
         
            +
                  subject.should be_terminated
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
              context "given a wrong context" do
         
     | 
| 
      
 72 
     | 
    
         
            +
                subject { Cuttlebone::Session::Base.new('invalid_context') }
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                it "should indicate internal error" do
         
     | 
| 
      
 75 
     | 
    
         
            +
                  subject.internal_error.should_not be_blank
         
     | 
| 
      
 76 
     | 
    
         
            +
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                it "should be terminated" do
         
     | 
| 
      
 79 
     | 
    
         
            +
                  subject.should be_terminated
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
              end
         
     | 
| 
      
 82 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/spec.opts
    ADDED
    
    
    
        data/spec/spec_helper.rb
    ADDED
    
    | 
         @@ -0,0 +1,8 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rspec'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'cuttlebone'))
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            RSpec.configure do |config|
         
     | 
| 
      
 5 
     | 
    
         
            +
              config.alias_it_should_behave_like_to(:it_should_behave_like, '')
         
     | 
| 
      
 6 
     | 
    
         
            +
              config.filter_run :focused => true
         
     | 
| 
      
 7 
     | 
    
         
            +
              config.run_all_when_everything_filtered = true
         
     | 
| 
      
 8 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,56 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # (active_support)/lib/active_support/core_ext/module/remove_method.rb
         
     | 
| 
      
 2 
     | 
    
         
            +
            class Module
         
     | 
| 
      
 3 
     | 
    
         
            +
              def remove_possible_method(method)
         
     | 
| 
      
 4 
     | 
    
         
            +
                remove_method(method)
         
     | 
| 
      
 5 
     | 
    
         
            +
              rescue NameError
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              def redefine_method(method, &block)
         
     | 
| 
      
 9 
     | 
    
         
            +
                remove_possible_method(method)
         
     | 
| 
      
 10 
     | 
    
         
            +
                define_method(method, &block)
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            # (active_support)/lib/active_support/core_ext/module/delegation.rb (stripped)
         
     | 
| 
      
 15 
     | 
    
         
            +
            class Module
         
     | 
| 
      
 16 
     | 
    
         
            +
              def delegate(*methods)
         
     | 
| 
      
 17 
     | 
    
         
            +
                options = methods.pop
         
     | 
| 
      
 18 
     | 
    
         
            +
                unless options.is_a?(Hash) && to = options[:to]
         
     | 
| 
      
 19 
     | 
    
         
            +
                  raise ArgumentError, "Delegation needs a target. Supply an options hash with a :to key as the last argument (e.g. delegate :hello, :to => :greeter)."
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                if options[:prefix] == true && options[:to].to_s =~ /^[^a-z_]/
         
     | 
| 
      
 23 
     | 
    
         
            +
                  raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_" || ''
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                file, line = caller.first.split(':', 2)
         
     | 
| 
      
 29 
     | 
    
         
            +
                line = line.to_i
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                methods.each do |method|
         
     | 
| 
      
 32 
     | 
    
         
            +
                  on_nil =
         
     | 
| 
      
 33 
     | 
    
         
            +
                    if options[:allow_nil]
         
     | 
| 
      
 34 
     | 
    
         
            +
                      'return'
         
     | 
| 
      
 35 
     | 
    
         
            +
                    else
         
     | 
| 
      
 36 
     | 
    
         
            +
                      %(raise "#{self}##{prefix}#{method} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}")
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  module_eval(<<-EOS, file, line - 5)
         
     | 
| 
      
 40 
     | 
    
         
            +
                    if instance_methods(false).map(&:to_s).include?("#{prefix}#{method}")
         
     | 
| 
      
 41 
     | 
    
         
            +
                      remove_possible_method("#{prefix}#{method}")
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    def #{prefix}#{method}(*args, &block)               # def customer_name(*args, &block)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      #{to}.__send__(#{method.inspect}, *args, &block)  #   client.__send__(:name, *args, &block)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    rescue NoMethodError                                # rescue NoMethodError
         
     | 
| 
      
 47 
     | 
    
         
            +
                      if #{to}.nil?                                     #   if client.nil?
         
     | 
| 
      
 48 
     | 
    
         
            +
                        #{on_nil}                                       #     return # depends on :allow_nil
         
     | 
| 
      
 49 
     | 
    
         
            +
                      else                                              #   else
         
     | 
| 
      
 50 
     | 
    
         
            +
                        raise                                           #     raise
         
     | 
| 
      
 51 
     | 
    
         
            +
                      end                                               #   end
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end                                                 # end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  EOS
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,142 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification 
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: cuttlebone
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version 
         
     | 
| 
      
 4 
     | 
    
         
            +
              prerelease: 
         
     | 
| 
      
 5 
     | 
    
         
            +
              version: 0.1.3
         
     | 
| 
      
 6 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 7 
     | 
    
         
            +
            authors: 
         
     | 
| 
      
 8 
     | 
    
         
            +
            - Bence Golda
         
     | 
| 
      
 9 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 10 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 11 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            date: 2011-03-18 00:00:00 +01:00
         
     | 
| 
      
 14 
     | 
    
         
            +
            default_executable: 
         
     | 
| 
      
 15 
     | 
    
         
            +
            dependencies: 
         
     | 
| 
      
 16 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 17 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 18 
     | 
    
         
            +
              requirement: &id001 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 19 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 20 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 21 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 22 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 23 
     | 
    
         
            +
                    version: 1.0.0
         
     | 
| 
      
 24 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 25 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 26 
     | 
    
         
            +
              version_requirements: *id001
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 28 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 29 
     | 
    
         
            +
              requirement: &id002 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 30 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 31 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 32 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 33 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 34 
     | 
    
         
            +
                    version: 2.5.0
         
     | 
| 
      
 35 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 36 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 37 
     | 
    
         
            +
              version_requirements: *id002
         
     | 
| 
      
 38 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 39 
     | 
    
         
            +
              name: i18n
         
     | 
| 
      
 40 
     | 
    
         
            +
              requirement: &id003 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 41 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 42 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 43 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 44 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 45 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 46 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 47 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 48 
     | 
    
         
            +
              version_requirements: *id003
         
     | 
| 
      
 49 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 50 
     | 
    
         
            +
              name: cucumber
         
     | 
| 
      
 51 
     | 
    
         
            +
              requirement: &id004 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 52 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 53 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 54 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 55 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 56 
     | 
    
         
            +
                    version: 0.10.0
         
     | 
| 
      
 57 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 58 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 59 
     | 
    
         
            +
              version_requirements: *id004
         
     | 
| 
      
 60 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 61 
     | 
    
         
            +
              name: rcov
         
     | 
| 
      
 62 
     | 
    
         
            +
              requirement: &id005 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 63 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 64 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 65 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 66 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 67 
     | 
    
         
            +
                    version: 0.9.0
         
     | 
| 
      
 68 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 69 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 70 
     | 
    
         
            +
              version_requirements: *id005
         
     | 
| 
      
 71 
     | 
    
         
            +
            description: Cuttlebone helps you creating shell-alike applications.
         
     | 
| 
      
 72 
     | 
    
         
            +
            email: 
         
     | 
| 
      
 73 
     | 
    
         
            +
            - bence@golda.me
         
     | 
| 
      
 74 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            extra_rdoc_files: 
         
     | 
| 
      
 79 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 80 
     | 
    
         
            +
            files: 
         
     | 
| 
      
 81 
     | 
    
         
            +
            - .gitignore
         
     | 
| 
      
 82 
     | 
    
         
            +
            - CHANGELOG.md
         
     | 
| 
      
 83 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 84 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 85 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 86 
     | 
    
         
            +
            - cuttlebone.gemspec
         
     | 
| 
      
 87 
     | 
    
         
            +
            - examples/todo.rb
         
     | 
| 
      
 88 
     | 
    
         
            +
            - features/example.feature
         
     | 
| 
      
 89 
     | 
    
         
            +
            - features/step_definitions/steps.rb
         
     | 
| 
      
 90 
     | 
    
         
            +
            - features/support/env.rb
         
     | 
| 
      
 91 
     | 
    
         
            +
            - features/support/test_driver.rb
         
     | 
| 
      
 92 
     | 
    
         
            +
            - features/switching_contexts.feature
         
     | 
| 
      
 93 
     | 
    
         
            +
            - lib/cuttlebone.rb
         
     | 
| 
      
 94 
     | 
    
         
            +
            - lib/cuttlebone/controller.rb
         
     | 
| 
      
 95 
     | 
    
         
            +
            - lib/cuttlebone/definition.rb
         
     | 
| 
      
 96 
     | 
    
         
            +
            - lib/cuttlebone/exceptions.rb
         
     | 
| 
      
 97 
     | 
    
         
            +
            - lib/cuttlebone/session.rb
         
     | 
| 
      
 98 
     | 
    
         
            +
            - lib/cuttlebone/session/base.rb
         
     | 
| 
      
 99 
     | 
    
         
            +
            - lib/cuttlebone/session/rack.rb
         
     | 
| 
      
 100 
     | 
    
         
            +
            - lib/cuttlebone/session/shell.rb
         
     | 
| 
      
 101 
     | 
    
         
            +
            - lib/cuttlebone/version.rb
         
     | 
| 
      
 102 
     | 
    
         
            +
            - spec/controller_spec.rb
         
     | 
| 
      
 103 
     | 
    
         
            +
            - spec/cuttlebone_spec.rb
         
     | 
| 
      
 104 
     | 
    
         
            +
            - spec/definition_spec.rb
         
     | 
| 
      
 105 
     | 
    
         
            +
            - spec/rcov.opts
         
     | 
| 
      
 106 
     | 
    
         
            +
            - spec/session_base_spec.rb
         
     | 
| 
      
 107 
     | 
    
         
            +
            - spec/spec.opts
         
     | 
| 
      
 108 
     | 
    
         
            +
            - spec/spec_helper.rb
         
     | 
| 
      
 109 
     | 
    
         
            +
            - vendor/active_support.rb
         
     | 
| 
      
 110 
     | 
    
         
            +
            has_rdoc: true
         
     | 
| 
      
 111 
     | 
    
         
            +
            homepage: http://github.com/gbence/cuttlebone
         
     | 
| 
      
 112 
     | 
    
         
            +
            licenses: []
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 115 
     | 
    
         
            +
            rdoc_options: 
         
     | 
| 
      
 116 
     | 
    
         
            +
            - --charset=UTF-8
         
     | 
| 
      
 117 
     | 
    
         
            +
            require_paths: 
         
     | 
| 
      
 118 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 119 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 120 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 121 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 122 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 123 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 124 
     | 
    
         
            +
                  hash: 2700429317005123117
         
     | 
| 
      
 125 
     | 
    
         
            +
                  segments: 
         
     | 
| 
      
 126 
     | 
    
         
            +
                  - 0
         
     | 
| 
      
 127 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 128 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 129 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 130 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 131 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 132 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 133 
     | 
    
         
            +
                  version: 1.3.7
         
     | 
| 
      
 134 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            rubyforge_project: cuttlebone
         
     | 
| 
      
 137 
     | 
    
         
            +
            rubygems_version: 1.5.3
         
     | 
| 
      
 138 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 139 
     | 
    
         
            +
            specification_version: 3
         
     | 
| 
      
 140 
     | 
    
         
            +
            summary: cuttlebone-0.1.3
         
     | 
| 
      
 141 
     | 
    
         
            +
            test_files: []
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     |