ego 0.3.0 → 0.4.0
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.
- checksums.yaml +4 -4
 - data/.travis.yml +4 -0
 - data/.yardopts +1 -0
 - data/README.md +40 -35
 - data/ego.gemspec +1 -0
 - data/lib/ego.rb +40 -3
 - data/lib/ego/capability.rb +30 -0
 - data/lib/ego/filesystem.rb +58 -29
 - data/lib/ego/handler.rb +62 -59
 - data/lib/ego/options.rb +14 -2
 - data/lib/ego/plugin.rb +58 -0
 - data/lib/ego/plugins/capabilities.rb +17 -0
 - data/lib/ego/plugins/fallback.rb +36 -0
 - data/lib/ego/plugins/robot_io.rb +16 -0
 - data/lib/ego/plugins/social.rb +19 -0
 - data/lib/ego/plugins/system.rb +21 -0
 - data/lib/ego/printer.rb +95 -0
 - data/lib/ego/robot.rb +157 -10
 - data/lib/ego/robot_error.rb +8 -0
 - data/lib/ego/runner.rb +51 -20
 - data/lib/ego/version.rb +2 -1
 - data/spec/ego/capability_spec.rb +23 -0
 - data/spec/ego/handler_spec.rb +63 -0
 - data/spec/ego/options_spec.rb +23 -13
 - data/spec/ego/plugin_spec.rb +68 -0
 - data/spec/ego/printer_spec.rb +120 -0
 - data/spec/ego/robot_error_spec.rb +12 -0
 - data/spec/ego/robot_spec.rb +283 -26
 - metadata +36 -10
 - data/lib/ego/formatter.rb +0 -36
 - data/lib/ego/handler/default.rb +0 -31
 - data/lib/ego/handler/echo.rb +0 -9
 - data/lib/ego/handler/greet.rb +0 -17
 - data/lib/ego/handler/handlers.rb +0 -15
 - data/lib/ego/handler/self.rb +0 -9
 - data/lib/ego/listener.rb +0 -25
 - data/spec/ego/formatter_spec.rb +0 -53
 
    
        data/lib/ego/runner.rb
    CHANGED
    
    | 
         @@ -1,73 +1,104 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require_relative '../ego'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require_relative 'options'
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
4 
     | 
    
         
             
            module Ego
         
     | 
| 
       4 
     | 
    
         
            -
              # The  
     | 
| 
       5 
     | 
    
         
            -
              #  
     | 
| 
      
 5 
     | 
    
         
            +
              # The Runner class, given an array of arguments, initializes the required
         
     | 
| 
      
 6 
     | 
    
         
            +
              # objects and executes the request.
         
     | 
| 
       6 
7 
     | 
    
         
             
              class Runner
         
     | 
| 
      
 8 
     | 
    
         
            +
                # Prompt to display in shell-mode
         
     | 
| 
       7 
9 
     | 
    
         
             
                PROMPT = 'ego, '.green.freeze
         
     | 
| 
      
 10 
     | 
    
         
            +
                # Pattern that triggers shell-mode to exit
         
     | 
| 
       8 
11 
     | 
    
         
             
                QUIT = /^q(uit)?|exit|(good)?bye$/.freeze
         
     | 
| 
       9 
12 
     | 
    
         | 
| 
       10 
13 
     | 
    
         
             
                # Takes an array of arguments and parses them into options:
         
     | 
| 
       11 
14 
     | 
    
         
             
                #
         
     | 
| 
      
 15 
     | 
    
         
            +
                # @example
         
     | 
| 
       12 
16 
     | 
    
         
             
                #   runner = Ego::Runner.new(ARGV)
         
     | 
| 
       13 
17 
     | 
    
         
             
                #
         
     | 
| 
      
 18 
     | 
    
         
            +
                # @param argv [Array] command-line arguments
         
     | 
| 
       14 
19 
     | 
    
         
             
                def initialize(argv)
         
     | 
| 
       15 
20 
     | 
    
         
             
                  @options = Options.new(argv)
         
     | 
| 
       16 
     | 
    
         
            -
                  @formatter = Ego::Formatter.new
         
     | 
| 
       17 
21 
     | 
    
         
             
                end
         
     | 
| 
       18 
22 
     | 
    
         | 
| 
       19 
23 
     | 
    
         
             
                # Run the appropriate action based on the arguments provided to
         
     | 
| 
       20 
     | 
    
         
            -
                #  
     | 
| 
      
 24 
     | 
    
         
            +
                # `#initialize`.
         
     | 
| 
      
 25 
     | 
    
         
            +
                #
         
     | 
| 
      
 26 
     | 
    
         
            +
                # @return [void]
         
     | 
| 
       21 
27 
     | 
    
         
             
                def run
         
     | 
| 
       22 
28 
     | 
    
         
             
                  case @options.mode
         
     | 
| 
       23 
29 
     | 
    
         
             
                  when :help
         
     | 
| 
       24 
30 
     | 
    
         
             
                    if @options.usage_error
         
     | 
| 
       25 
     | 
    
         
            -
                       
     | 
| 
      
 31 
     | 
    
         
            +
                      Printer.errs @options.usage_error, "\n"
         
     | 
| 
       26 
32 
     | 
    
         
             
                    end
         
     | 
| 
       27 
33 
     | 
    
         | 
| 
       28 
     | 
    
         
            -
                     
     | 
| 
      
 34 
     | 
    
         
            +
                    Printer.puts @options.usage
         
     | 
| 
       29 
35 
     | 
    
         | 
| 
       30 
36 
     | 
    
         
             
                    exit(-1) if @options.usage_error
         
     | 
| 
       31 
37 
     | 
    
         
             
                  when :version
         
     | 
| 
       32 
     | 
    
         
            -
                     
     | 
| 
      
 38 
     | 
    
         
            +
                    Printer.puts "ego v#{Ego::VERSION}"
         
     | 
| 
       33 
39 
     | 
    
         
             
                  when :shell
         
     | 
| 
       34 
     | 
    
         
            -
                     
     | 
| 
       35 
     | 
    
         
            -
                    start_repl
         
     | 
| 
      
 40 
     | 
    
         
            +
                    start_shell(robot_factory)
         
     | 
| 
       36 
41 
     | 
    
         
             
                  else
         
     | 
| 
       37 
     | 
    
         
            -
                     
     | 
| 
       38 
     | 
    
         
            -
                    handle_query @options.query
         
     | 
| 
      
 42 
     | 
    
         
            +
                    handle_query(robot_factory, @options.query)
         
     | 
| 
       39 
43 
     | 
    
         
             
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                rescue RobotError => e
         
     | 
| 
      
 45 
     | 
    
         
            +
                  Printer.errs e.message
         
     | 
| 
      
 46 
     | 
    
         
            +
                  exit(-2)
         
     | 
| 
       40 
47 
     | 
    
         
             
                end
         
     | 
| 
       41 
48 
     | 
    
         | 
| 
       42 
49 
     | 
    
         
             
                protected
         
     | 
| 
       43 
50 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
                 
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
      
 51 
     | 
    
         
            +
                # Get a robot and enhance it with plug-ins.
         
     | 
| 
      
 52 
     | 
    
         
            +
                #
         
     | 
| 
      
 53 
     | 
    
         
            +
                # @return [Robot] a decorated robot instance
         
     | 
| 
      
 54 
     | 
    
         
            +
                def robot_factory
         
     | 
| 
      
 55 
     | 
    
         
            +
                  Plugin.load Filesystem.builtin_plugins
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  if @options.plugins
         
     | 
| 
      
 58 
     | 
    
         
            +
                    Plugin.load Filesystem.user_plugins
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  Plugin.decorate(Robot.new(@options)).ready
         
     | 
| 
       48 
62 
     | 
    
         
             
                end
         
     | 
| 
       49 
63 
     | 
    
         | 
| 
       50 
     | 
    
         
            -
                 
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
      
 64 
     | 
    
         
            +
                # Handle and single query and shut down.
         
     | 
| 
      
 65 
     | 
    
         
            +
                #
         
     | 
| 
      
 66 
     | 
    
         
            +
                # @param robot [Robot] the robot to handle the query
         
     | 
| 
      
 67 
     | 
    
         
            +
                # @param query [String] the query to handle
         
     | 
| 
      
 68 
     | 
    
         
            +
                # @return [void]
         
     | 
| 
      
 69 
     | 
    
         
            +
                def handle_query(robot, query)
         
     | 
| 
      
 70 
     | 
    
         
            +
                  robot.handle(query)
         
     | 
| 
      
 71 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 72 
     | 
    
         
            +
                  robot.shutdown
         
     | 
| 
       52 
73 
     | 
    
         
             
                end
         
     | 
| 
       53 
74 
     | 
    
         | 
| 
      
 75 
     | 
    
         
            +
                # Show a prompt and read input from the user.
         
     | 
| 
      
 76 
     | 
    
         
            +
                #
         
     | 
| 
      
 77 
     | 
    
         
            +
                # @return [String, nil] the user query
         
     | 
| 
       54 
78 
     | 
    
         
             
                def prompt
         
     | 
| 
       55 
79 
     | 
    
         
             
                  Readline.readline(PROMPT, true)
         
     | 
| 
       56 
80 
     | 
    
         
             
                end
         
     | 
| 
       57 
81 
     | 
    
         | 
| 
       58 
     | 
    
         
            -
                 
     | 
| 
      
 82 
     | 
    
         
            +
                # Start a REPL for handling multiple queries in one session.
         
     | 
| 
      
 83 
     | 
    
         
            +
                #
         
     | 
| 
      
 84 
     | 
    
         
            +
                # @param robot [Robot] the robot to handle the query
         
     | 
| 
      
 85 
     | 
    
         
            +
                # @return [void]
         
     | 
| 
      
 86 
     | 
    
         
            +
                def start_shell(robot)
         
     | 
| 
       59 
87 
     | 
    
         
             
                  require 'readline'
         
     | 
| 
       60 
88 
     | 
    
         | 
| 
       61 
     | 
    
         
            -
                  #  
     | 
| 
      
 89 
     | 
    
         
            +
                  # Save the state of the terminal
         
     | 
| 
       62 
90 
     | 
    
         
             
                  stty_save = `stty -g`.chomp
         
     | 
| 
       63 
91 
     | 
    
         | 
| 
       64 
92 
     | 
    
         
             
                  loop do
         
     | 
| 
       65 
93 
     | 
    
         
             
                    query = prompt
         
     | 
| 
       66 
94 
     | 
    
         
             
                    break if query.nil? || query.strip =~ QUIT
         
     | 
| 
       67 
     | 
    
         
            -
                     
     | 
| 
      
 95 
     | 
    
         
            +
                    robot.handle(query.strip)
         
     | 
| 
       68 
96 
     | 
    
         
             
                  end
         
     | 
| 
       69 
97 
     | 
    
         
             
                rescue Interrupt => e
         
     | 
| 
       70 
98 
     | 
    
         
             
                  system('stty', stty_save) # Restore state
         
     | 
| 
      
 99 
     | 
    
         
            +
                  robot.say e.message
         
     | 
| 
      
 100 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 101 
     | 
    
         
            +
                  robot.shutdown
         
     | 
| 
       71 
102 
     | 
    
         
             
                end
         
     | 
| 
       72 
103 
     | 
    
         
             
              end
         
     | 
| 
       73 
104 
     | 
    
         
             
            end
         
     | 
    
        data/lib/ego/version.rb
    CHANGED
    
    
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'ego/capability'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec.describe Ego::Capability do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:desc) { 'my desc' }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:plugin) { double('Ego::Plugin') }
         
     | 
| 
      
 6 
     | 
    
         
            +
              subject { described_class.new(desc, plugin) }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              context 'on initization' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                it 'sets its description' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                  expect(subject.desc).to eq(desc)
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                it 'sets its plug-in' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                  expect(subject.plugin).to be plugin
         
     | 
| 
      
 15 
     | 
    
         
            +
                end
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              describe '#to_s' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                it 'returns the description' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                  expect(subject.to_s).to eq(desc)
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'ego/handler'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec.describe Ego::Handler do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:condition) { ->(q) { 'bar' if q == 'foo' } }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:regexp) { /^baz/i }
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:action) { ->(p) { puts p } }
         
     | 
| 
      
 7 
     | 
    
         
            +
              let(:priority) { 2 }
         
     | 
| 
      
 8 
     | 
    
         
            +
              subject { described_class.new(condition, action, priority) }
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              context 'on initization' do
         
     | 
| 
      
 11 
     | 
    
         
            +
                it 'sets its condition' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                  expect(subject.condition).to be condition
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                it 'sets its action' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                  expect(subject.action).to be action
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                it 'sets its priority' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                  expect(subject.priority).to be priority
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                it 'defaults its priority to 5' do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  default_handler = described_class.new(condition, action)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  expect(default_handler.priority).to eq(5)
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                describe 'given something matchable as the condition' do
         
     | 
| 
      
 29 
     | 
    
         
            +
                  it 'encloses it' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                    expect(regexp.respond_to?(:match)).to be true
         
     | 
| 
      
 31 
     | 
    
         
            +
                    expect(regexp.respond_to?(:call)).to be false
         
     | 
| 
      
 32 
     | 
    
         
            +
                    regexp_handler = described_class.new(regexp, action, priority)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    expect(regexp_handler.condition.respond_to?(:match)).to be false
         
     | 
| 
      
 34 
     | 
    
         
            +
                    expect(regexp_handler.condition.respond_to?(:call)).to be true
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              it 'is comparable' do
         
     | 
| 
      
 40 
     | 
    
         
            +
                expect(subject.respond_to?(:'<=>')).to be true
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
              it 'compares priorities' do
         
     | 
| 
      
 44 
     | 
    
         
            +
                handler1 = described_class.new(condition, action, 1)
         
     | 
| 
      
 45 
     | 
    
         
            +
                handler2 = described_class.new(condition, action, 2)
         
     | 
| 
      
 46 
     | 
    
         
            +
                expect(handler2).to be > handler1
         
     | 
| 
      
 47 
     | 
    
         
            +
                expect(handler1).to be < handler2
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
              describe '#handle' do
         
     | 
| 
      
 51 
     | 
    
         
            +
                context 'when the query cannot be handled' do
         
     | 
| 
      
 52 
     | 
    
         
            +
                  it 'returns false' do
         
     | 
| 
      
 53 
     | 
    
         
            +
                    expect(subject.handle('fail')).to be false
         
     | 
| 
      
 54 
     | 
    
         
            +
                  end
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                context 'when the query can be handled' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                  it 'returns the result of the condition closure' do
         
     | 
| 
      
 59 
     | 
    
         
            +
                    expect(subject.handle('foo')).to eq('bar')
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/ego/options_spec.rb
    CHANGED
    
    | 
         @@ -2,68 +2,78 @@ require 'ego/options' 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            RSpec.describe Ego::Options do
         
     | 
| 
       4 
4 
     | 
    
         
             
              it 'defaults to interpret-mode' do
         
     | 
| 
       5 
     | 
    
         
            -
                opts =  
     | 
| 
      
 5 
     | 
    
         
            +
                opts = described_class.new(['foo'])
         
     | 
| 
       6 
6 
     | 
    
         
             
                expect(opts.mode).to eq(:interpret)
         
     | 
| 
       7 
7 
     | 
    
         
             
              end
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
              it 'can be set to shell-mode' do
         
     | 
| 
       10 
     | 
    
         
            -
                opts =  
     | 
| 
      
 10 
     | 
    
         
            +
                opts = described_class.new(['-s'])
         
     | 
| 
       11 
11 
     | 
    
         
             
                expect(opts.mode).to eq(:shell)
         
     | 
| 
       12 
12 
     | 
    
         
             
              end
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
              it 'can be set to version-mode' do
         
     | 
| 
       15 
     | 
    
         
            -
                opts =  
     | 
| 
      
 15 
     | 
    
         
            +
                opts = described_class.new(['-v'])
         
     | 
| 
       16 
16 
     | 
    
         
             
                expect(opts.mode).to eq(:version)
         
     | 
| 
       17 
17 
     | 
    
         
             
              end
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
              it 'can be set to help-mode' do
         
     | 
| 
       20 
     | 
    
         
            -
                opts =  
     | 
| 
      
 20 
     | 
    
         
            +
                opts = described_class.new(['-h'])
         
     | 
| 
       21 
21 
     | 
    
         
             
                expect(opts.mode).to eq(:help)
         
     | 
| 
       22 
22 
     | 
    
         
             
              end
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
              it 'defaults to help-mode with no arguments' do
         
     | 
| 
       25 
     | 
    
         
            -
                opts =  
     | 
| 
      
 25 
     | 
    
         
            +
                opts = described_class.new([])
         
     | 
| 
       26 
26 
     | 
    
         
             
                expect(opts.mode).to eq(:help)
         
     | 
| 
       27 
27 
     | 
    
         
             
              end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
      
 29 
     | 
    
         
            +
              it 'defaults to loading user plug-ins' do
         
     | 
| 
      
 30 
     | 
    
         
            +
                opts = described_class.new(['foo'])
         
     | 
| 
      
 31 
     | 
    
         
            +
                expect(opts.plugins).to be true
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              it 'can be set to not load user plug-ins' do
         
     | 
| 
      
 35 
     | 
    
         
            +
                opts = described_class.new(['-n', 'foo'])
         
     | 
| 
      
 36 
     | 
    
         
            +
                expect(opts.plugins).to be false
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
       29 
39 
     | 
    
         
             
              it 'defaults to not verbose' do
         
     | 
| 
       30 
     | 
    
         
            -
                opts =  
     | 
| 
      
 40 
     | 
    
         
            +
                opts = described_class.new(['foo'])
         
     | 
| 
       31 
41 
     | 
    
         
             
                expect(opts.verbose).to be false
         
     | 
| 
       32 
42 
     | 
    
         
             
              end
         
     | 
| 
       33 
43 
     | 
    
         | 
| 
       34 
44 
     | 
    
         
             
              it 'can be set to verbose' do
         
     | 
| 
       35 
     | 
    
         
            -
                opts =  
     | 
| 
      
 45 
     | 
    
         
            +
                opts = described_class.new(['-V', 'foo'])
         
     | 
| 
       36 
46 
     | 
    
         
             
                expect(opts.verbose).to be true
         
     | 
| 
       37 
47 
     | 
    
         
             
              end
         
     | 
| 
       38 
48 
     | 
    
         | 
| 
       39 
49 
     | 
    
         
             
              it 'sets the query to remaining args join with spaces' do
         
     | 
| 
       40 
     | 
    
         
            -
                opts =  
     | 
| 
      
 50 
     | 
    
         
            +
                opts = described_class.new(['foo', 'bar'])
         
     | 
| 
       41 
51 
     | 
    
         
             
                expect(opts.query).to eq('foo bar')
         
     | 
| 
       42 
52 
     | 
    
         
             
              end
         
     | 
| 
       43 
53 
     | 
    
         | 
| 
       44 
54 
     | 
    
         
             
              it 'sets the robot name' do
         
     | 
| 
       45 
     | 
    
         
            -
                opts =  
     | 
| 
      
 55 
     | 
    
         
            +
                opts = described_class.new(['foo'])
         
     | 
| 
       46 
56 
     | 
    
         
             
                expect(opts.robot_name).to_not be_nil
         
     | 
| 
       47 
57 
     | 
    
         
             
              end
         
     | 
| 
       48 
58 
     | 
    
         | 
| 
       49 
59 
     | 
    
         
             
              it 'sets the usage' do
         
     | 
| 
       50 
     | 
    
         
            -
                opts =  
     | 
| 
      
 60 
     | 
    
         
            +
                opts = described_class.new(['foo'])
         
     | 
| 
       51 
61 
     | 
    
         
             
                expect(opts.usage).to be_instance_of OptionParser
         
     | 
| 
       52 
62 
     | 
    
         
             
              end
         
     | 
| 
       53 
63 
     | 
    
         | 
| 
       54 
64 
     | 
    
         
             
              it 'does not set a usage error normally' do
         
     | 
| 
       55 
     | 
    
         
            -
                opts =  
     | 
| 
      
 65 
     | 
    
         
            +
                opts = described_class.new(['foo'])
         
     | 
| 
       56 
66 
     | 
    
         
             
                expect(opts.usage_error).to be_nil
         
     | 
| 
       57 
67 
     | 
    
         
             
              end
         
     | 
| 
       58 
68 
     | 
    
         | 
| 
       59 
69 
     | 
    
         
             
              context 'with invalid option' do
         
     | 
| 
       60 
70 
     | 
    
         
             
                it 'sets a usage error message' do
         
     | 
| 
       61 
     | 
    
         
            -
                  opts =  
     | 
| 
      
 71 
     | 
    
         
            +
                  opts = described_class.new(['--does-not-exist'])
         
     | 
| 
       62 
72 
     | 
    
         
             
                  expect(opts.usage_error).to eq('invalid option: --does-not-exist')
         
     | 
| 
       63 
73 
     | 
    
         
             
                end
         
     | 
| 
       64 
74 
     | 
    
         | 
| 
       65 
75 
     | 
    
         
             
                it 'sets help-mode' do
         
     | 
| 
       66 
     | 
    
         
            -
                  opts =  
     | 
| 
      
 76 
     | 
    
         
            +
                  opts = described_class.new(['--does-not-exist'])
         
     | 
| 
       67 
77 
     | 
    
         
             
                  expect(opts.mode).to eq(:help)
         
     | 
| 
       68 
78 
     | 
    
         
             
                end
         
     | 
| 
       69 
79 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,68 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'ego/plugin'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            RSpec.describe Ego::Plugin do
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:name) { 'my_plug' }
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:body) { proc { true } }
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:plugin) { described_class.new(name, body) }
         
     | 
| 
      
 7 
     | 
    
         
            +
              let(:builtin_plugin) { described_class.new(name, body, builtin: true) }
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              context 'on initization' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                it 'sets its name' do
         
     | 
| 
      
 11 
     | 
    
         
            +
                  expect(plugin.name).to eq(name)
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                it 'sets its body' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                  expect(plugin.body).to be body
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                it 'sets its builtin flag' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                  expect(builtin_plugin.builtin).to be true
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                it 'defaults its builtin flag to false' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                  expect(plugin.builtin).to be false
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              describe '.register' do
         
     | 
| 
      
 28 
     | 
    
         
            +
                it 'returns a new plugin' do
         
     | 
| 
      
 29 
     | 
    
         
            +
                  expect(described_class.register(name, body)).to be_instance_of(described_class)
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
              end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
              describe '.decorate' do
         
     | 
| 
      
 35 
     | 
    
         
            +
                let(:obj) do
         
     | 
| 
      
 36 
     | 
    
         
            +
                  Class.new { attr_accessor :context, :a, :b }.new
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                before do
         
     | 
| 
      
 40 
     | 
    
         
            +
                  described_class.class_variable_set :@@plugins, {}
         
     | 
| 
      
 41 
     | 
    
         
            +
                  described_class.register('a', proc { |obj|
         
     | 
| 
      
 42 
     | 
    
         
            +
                    obj.a = 'foo'
         
     | 
| 
      
 43 
     | 
    
         
            +
                  })
         
     | 
| 
      
 44 
     | 
    
         
            +
                  described_class.register('b', proc { |obj|
         
     | 
| 
      
 45 
     | 
    
         
            +
                    obj.b = 'bar'
         
     | 
| 
      
 46 
     | 
    
         
            +
                  })
         
     | 
| 
      
 47 
     | 
    
         
            +
                end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                it 'sets obj#context to each registered plugin' do
         
     | 
| 
      
 50 
     | 
    
         
            +
                  expect(obj).to receive(:context=).twice
         
     | 
| 
      
 51 
     | 
    
         
            +
                  described_class.decorate(obj)
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                it 'calls each plugin body passing the obj' do
         
     | 
| 
      
 55 
     | 
    
         
            +
                  expect(obj).to receive_messages({
         
     | 
| 
      
 56 
     | 
    
         
            +
                    :a= => 'foo',
         
     | 
| 
      
 57 
     | 
    
         
            +
                    :b= => 'bar',
         
     | 
| 
      
 58 
     | 
    
         
            +
                  })
         
     | 
| 
      
 59 
     | 
    
         
            +
                  described_class.decorate(obj)
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                it 'returns the decorated obj' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  decorated = described_class.decorate(obj)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  expect(decorated.a).to eq('foo')
         
     | 
| 
      
 65 
     | 
    
         
            +
                  expect(decorated.b).to eq('bar')
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
              end
         
     | 
| 
      
 68 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,120 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'ego/printer'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Ego
         
     | 
| 
      
 4 
     | 
    
         
            +
              RSpec.describe Printer do
         
     | 
| 
      
 5 
     | 
    
         
            +
                let(:verbose_printer) { (Class.new { include Printer; def verbose?; true; end }).new }
         
     | 
| 
      
 6 
     | 
    
         
            +
                let(:printer) { (Class.new { include Printer }).new }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                describe '#puts' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  it 'is callable on the module' do
         
     | 
| 
      
 10 
     | 
    
         
            +
                    expect(described_class.respond_to?(:puts)).to be true
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  it 'is private on the instance' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                    expect(printer.respond_to?(:puts)).to be false
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  it 'prints to STDOUT' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                    expect { described_class.puts 'bar' }.to output("bar\n").to_stdout
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  it 'concatenates multiple arguments' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                    expect { described_class.puts 'bar', 'baz' }.to output("bar\nbaz\n").to_stdout
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                describe '#errs' do
         
     | 
| 
      
 27 
     | 
    
         
            +
                  it 'is callable on the module' do
         
     | 
| 
      
 28 
     | 
    
         
            +
                    expect(described_class.respond_to?(:errs)).to be true
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  it 'is private on the instance' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                    expect(printer.respond_to?(:errs)).to be false
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  it 'prints to STDERR' do
         
     | 
| 
      
 36 
     | 
    
         
            +
                    expect { described_class.errs 'bar' }.to output("bar\n").to_stderr
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  it 'concatenates multiple arguments' do
         
     | 
| 
      
 40 
     | 
    
         
            +
                    expect { described_class.errs 'bar', 'baz' }.to output("bar\nbaz\n").to_stderr
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                describe '#say' do
         
     | 
| 
      
 45 
     | 
    
         
            +
                  it 'is not callable on the module' do
         
     | 
| 
      
 46 
     | 
    
         
            +
                    expect(described_class.respond_to?(:say)).to be false
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  it 'is callable on the instance' do
         
     | 
| 
      
 50 
     | 
    
         
            +
                    expect(printer.respond_to?(:say)).to be true
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  it 'prints the message to STDOUT bolded with newline' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                    expect { printer.say('X') }.to output("\e[1;39;49mX\e[0m\n").to_stdout
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                  it 'accepts placeholders and replacement strings' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                    expect { printer.say('Hello, %s.', 'world') }.to output("\e[1;39;49mHello, world.\e[0m\n").to_stdout
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                describe '#emote' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  it 'is not callable on the module' do
         
     | 
| 
      
 64 
     | 
    
         
            +
                    expect(described_class.respond_to?(:emote)).to be false
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  it 'is callable on the instance' do
         
     | 
| 
      
 68 
     | 
    
         
            +
                    expect(printer.respond_to?(:emote)).to be true
         
     | 
| 
      
 69 
     | 
    
         
            +
                  end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                  it 'prints the message to STDOUT with color and asterisks' do
         
     | 
| 
      
 72 
     | 
    
         
            +
                    expect { printer.emote('FOO') }.to output("\e[0;35;49m*FOO*\e[0m\n").to_stdout
         
     | 
| 
      
 73 
     | 
    
         
            +
                  end
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                describe '#alert' do
         
     | 
| 
      
 77 
     | 
    
         
            +
                  it 'is not callable on the module' do
         
     | 
| 
      
 78 
     | 
    
         
            +
                    expect(described_class.respond_to?(:alert)).to be false
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                  it 'is callable on the instance' do
         
     | 
| 
      
 82 
     | 
    
         
            +
                    expect(printer.respond_to?(:alert)).to be true
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  it 'prints the message to STDERR with color and newline' do
         
     | 
| 
      
 86 
     | 
    
         
            +
                    expect { printer.alert('FOO') }.to output("\e[0;91;49mFOO\e[0m\n").to_stderr
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
                  it 'accepts placeholders and replacement strings' do
         
     | 
| 
      
 90 
     | 
    
         
            +
                    expect { printer.alert('Error: %s.', 'foo') }.to output("\e[0;91;49mError: foo.\e[0m\n").to_stderr
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                describe '#debug' do
         
     | 
| 
      
 95 
     | 
    
         
            +
                  it 'is not callable on the module' do
         
     | 
| 
      
 96 
     | 
    
         
            +
                    expect(described_class.respond_to?(:debug)).to be false
         
     | 
| 
      
 97 
     | 
    
         
            +
                  end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  it 'is callable on the instance' do
         
     | 
| 
      
 100 
     | 
    
         
            +
                    expect(printer.respond_to?(:debug)).to be true
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                  context 'in verbose instance' do
         
     | 
| 
      
 104 
     | 
    
         
            +
                    it 'prints the message to STDERR with newline' do
         
     | 
| 
      
 105 
     | 
    
         
            +
                      expect { verbose_printer.debug('FOO') }.to output("FOO\n").to_stderr
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
                    it 'accepts placeholders and replacement strings' do
         
     | 
| 
      
 109 
     | 
    
         
            +
                      expect { verbose_printer.debug('Hello, %s.', 'world') }.to output("Hello, world.\n").to_stderr
         
     | 
| 
      
 110 
     | 
    
         
            +
                    end
         
     | 
| 
      
 111 
     | 
    
         
            +
                  end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                  context 'in default instance' do
         
     | 
| 
      
 114 
     | 
    
         
            +
                    it 'does not print anything' do
         
     | 
| 
      
 115 
     | 
    
         
            +
                      expect { printer.debug('FOO') }.not_to output.to_stderr
         
     | 
| 
      
 116 
     | 
    
         
            +
                    end
         
     | 
| 
      
 117 
     | 
    
         
            +
                  end
         
     | 
| 
      
 118 
     | 
    
         
            +
                end
         
     | 
| 
      
 119 
     | 
    
         
            +
              end
         
     | 
| 
      
 120 
     | 
    
         
            +
            end
         
     |