hairballs 0.0.1 → 0.1.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/History.md +11 -0
- data/README.md +3 -3
- data/hairballs.gemspec +1 -1
- data/lib/hairballs/configuration.rb +170 -0
- data/lib/hairballs/library_helpers.rb +11 -8
- data/lib/hairballs/plugin.rb +8 -7
- data/lib/hairballs/plugins/awesome_print.rb +1 -1
- data/lib/hairballs/plugins/colorize_json.rb +1 -1
- data/lib/hairballs/plugins/interesting_methods.rb +1 -1
- data/lib/hairballs/plugins/irb_history.rb +1 -1
- data/lib/hairballs/plugins/object_ri.rb +1 -1
- data/lib/hairballs/plugins/quick_benchmark.rb +1 -1
- data/lib/hairballs/plugins/require_project_lib.rb +1 -1
- data/lib/hairballs/plugins/tab_completion_for_files.rb +10 -6
- data/lib/hairballs/plugins/wirble.rb +1 -1
- data/lib/hairballs/theme.rb +3 -4
- data/lib/hairballs/themes/turboladen.rb +4 -4
- data/lib/hairballs/themes/turboladen_rails.rb +4 -4
- data/lib/hairballs/version.rb +1 -1
- data/lib/hairballs.rb +23 -103
- data/spec/hairballs/configuration_spec.rb +195 -0
- data/spec/hairballs/library_helpers_spec.rb +72 -0
- data/spec/hairballs/plugin_spec.rb +72 -0
- data/spec/hairballs/theme_spec.rb +11 -0
- data/spec/hairballs_spec.rb +17 -173
- metadata +13 -4
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d253d151df5fdf784c216a8785627d1f0881cb01
         | 
| 4 | 
            +
              data.tar.gz: 45bce4a52cd3d2e01f48a3765b9fef39fffb36bc
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 0ca0f9c162b224b218184fd8afd15731ed52d220ff24032e75896cca7ed3bae272e6da15016f2556cbdcf7ec251e0dddbc01361b5dfd2f6fe1db076dadf1d3ff
         | 
| 7 | 
            +
              data.tar.gz: baff3f4a22ebfe513bba046a54486bf67da351bee1b8ea7f4365a7a21d9ef7e7f8c63f74775cb0c109b756fce5d28aae93389e368647dee838bb8e00fe38e8a1
         | 
    
        data/History.md
    CHANGED
    
    | @@ -1,3 +1,14 @@ | |
| 1 | 
            +
            ### 0.1.0 / 2015-02-18
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Improvements
         | 
| 4 | 
            +
                * Added `Hairballs.project_root`, which tries to determine the root
         | 
| 5 | 
            +
                  directory for the project you're working in.
         | 
| 6 | 
            +
                * Refactored configuration to Hairballs::Configuration.
         | 
| 7 | 
            +
            * Bug Fixes
         | 
| 8 | 
            +
                * Fixed nested file completion for the `tab_completion_for_files` plugin.
         | 
| 9 | 
            +
                * Fixed `Hairballs::LibraryHelpers#find_latest_gem` to find the latest
         | 
| 10 | 
            +
                  instead of the earliest.
         | 
| 11 | 
            +
             | 
| 1 12 | 
             
            ### 0.0.1 / 2014-12-19
         | 
| 2 13 |  | 
| 3 14 | 
             
            * Happy Birthday!
         | 
    
        data/README.md
    CHANGED
    
    | @@ -105,10 +105,10 @@ end | |
| 105 105 | 
             
            ```ruby
         | 
| 106 106 | 
             
            # hairballs/themes/turboladen_rails.rb
         | 
| 107 107 | 
             
            Hairballs.add_theme(:turboladen_rails) do |theme|
         | 
| 108 | 
            -
              theme.libraries do
         | 
| 109 | 
            -
                 | 
| 108 | 
            +
              theme.libraries do |libs|
         | 
| 109 | 
            +
                libs += %w(irb/completion looksee wirble awesome_print)
         | 
| 110 110 |  | 
| 111 | 
            -
                 | 
| 111 | 
            +
                libs +=
         | 
| 112 112 | 
             
                  case RUBY_PLATFORM
         | 
| 113 113 | 
             
                  when /mswin32|mingw32/
         | 
| 114 114 | 
             
                    %w(win32console)
         | 
    
        data/hairballs.gemspec
    CHANGED
    
    | @@ -9,7 +9,7 @@ Gem::Specification.new do |spec| | |
| 9 9 | 
             
              spec.authors       = ['Steve Loveless']
         | 
| 10 10 | 
             
              spec.email         = ['steve.loveless@gmail.com']
         | 
| 11 11 | 
             
              spec.summary       = 'Like oh-my-zsh, but for IRB.'
         | 
| 12 | 
            -
              spec.description   =  | 
| 12 | 
            +
              spec.description   = spec.summary
         | 
| 13 13 | 
             
              spec.homepage      = 'https://github.com/turboladen/hairballs'
         | 
| 14 14 | 
             
              spec.license       = 'MIT'
         | 
| 15 15 |  | 
| @@ -0,0 +1,170 @@ | |
| 1 | 
            +
            require 'open3'
         | 
| 2 | 
            +
            require 'pathname'
         | 
| 3 | 
            +
            require 'ostruct'
         | 
| 4 | 
            +
            require 'hairballs/ext/kernel_vputs'
         | 
| 5 | 
            +
            require 'hairballs/exceptions'
         | 
| 6 | 
            +
            require 'hairballs/theme'
         | 
| 7 | 
            +
            require 'hairballs/plugin'
         | 
| 8 | 
            +
            require 'hairballs/version'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            class Hairballs
         | 
| 11 | 
            +
              class Configuration
         | 
| 12 | 
            +
                # @return [Array<Hairballs::Theme>]
         | 
| 13 | 
            +
                attr_reader :themes
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                # @return [Hairballs::Theme]
         | 
| 16 | 
            +
                attr_reader :current_theme
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                # All Hairballs::Plugins available to be loaded.
         | 
| 19 | 
            +
                #
         | 
| 20 | 
            +
                # @return [Array<Hairballs::Plugin>]
         | 
| 21 | 
            +
                attr_reader :plugins
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                # All Hairballs::Plugins that have been loaded.
         | 
| 24 | 
            +
                #
         | 
| 25 | 
            +
                # @return [Array<Hairballs::Plugin>]
         | 
| 26 | 
            +
                attr_reader :loaded_plugins
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                # Used for maintaining all possible completion Procs, thus allowing many
         | 
| 29 | 
            +
                # different plugins to define a Proc for completion without overriding Procs
         | 
| 30 | 
            +
                # defined for other plugins.
         | 
| 31 | 
            +
                #
         | 
| 32 | 
            +
                # @return [Array<Proc>]
         | 
| 33 | 
            +
                attr_reader :completion_procs
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                # @return [String]
         | 
| 36 | 
            +
                attr_reader :project_name
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                # @return [String]
         | 
| 39 | 
            +
                attr_reader :project_root
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                def initialize
         | 
| 42 | 
            +
                  @themes = []
         | 
| 43 | 
            +
                  @current_theme = nil
         | 
| 44 | 
            +
                  @plugins = []
         | 
| 45 | 
            +
                  @loaded_plugins = []
         | 
| 46 | 
            +
                  @completion_procs = []
         | 
| 47 | 
            +
                  @project_name = nil
         | 
| 48 | 
            +
                  @project_root = nil
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                # @return [String]
         | 
| 52 | 
            +
                def version
         | 
| 53 | 
            +
                  Hairballs::VERSION
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                # Is IRB getting loaded for a rails console?
         | 
| 57 | 
            +
                #
         | 
| 58 | 
            +
                # @return [Boolean]
         | 
| 59 | 
            +
                def rails?
         | 
| 60 | 
            +
                  ENV.has_key?('RAILS_ENV') || !!defined?(Rails)
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                # Name of the relative directory.
         | 
| 64 | 
            +
                #
         | 
| 65 | 
            +
                # @return [String]
         | 
| 66 | 
            +
                def project_name
         | 
| 67 | 
            +
                  @project_name ||= File.basename(project_root)
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                def project_root
         | 
| 71 | 
            +
                  @project_root ||= find_project_root
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                def project_root?(path)
         | 
| 75 | 
            +
                  File.expand_path(path) == project_root
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                # Builds a new Hairballs::Theme and adds it to the list of `.themes` that
         | 
| 79 | 
            +
                # can be used.
         | 
| 80 | 
            +
                #
         | 
| 81 | 
            +
                # @param [Symbol] name Name to give the new Theme.
         | 
| 82 | 
            +
                # @return [Theme]
         | 
| 83 | 
            +
                def add_theme(name)
         | 
| 84 | 
            +
                  theme = Theme.new(name)
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                  yield theme
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                  themes << theme
         | 
| 89 | 
            +
                  vputs "Added theme: #{name}"
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  theme
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                # Tells IRB to use the Hairballs::Theme of +theme_name+.
         | 
| 95 | 
            +
                #
         | 
| 96 | 
            +
                # @param [Symbol] theme_name The name of the Theme to use/switch to.
         | 
| 97 | 
            +
                def use_theme(theme_name)
         | 
| 98 | 
            +
                  switch_to = themes.find { |theme| theme.name == theme_name }
         | 
| 99 | 
            +
                  fail ThemeUseFailure.new(theme_name) unless switch_to
         | 
| 100 | 
            +
                  vputs "Switched to theme: #{theme_name}"
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  switch_to.use!
         | 
| 103 | 
            +
                  @current_theme = switch_to
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  true
         | 
| 106 | 
            +
                end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                # Builds a new Hairballs::Plugin and adds it to thelist of `.plugins` that
         | 
| 109 | 
            +
                # can be used.
         | 
| 110 | 
            +
                #
         | 
| 111 | 
            +
                # @param [Symbol] name
         | 
| 112 | 
            +
                # @param [Hash] options Plugin-dependent options to define.  These get
         | 
| 113 | 
            +
                #   passed along the the Hairballs::Plugin object and are used as attributes
         | 
| 114 | 
            +
                #   of the plugin.
         | 
| 115 | 
            +
                def add_plugin(name, **options)
         | 
| 116 | 
            +
                  plugin = Plugin.new(name, options)
         | 
| 117 | 
            +
                  yield plugin
         | 
| 118 | 
            +
                  plugins << plugin
         | 
| 119 | 
            +
                  vputs "Added plugin: #{name}"
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                  plugin
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                # Searches for the Hairballs::Plugin by the +plugin_name+, then loads it.
         | 
| 125 | 
            +
                # Raises
         | 
| 126 | 
            +
                # @param plugin_name [Symbol]
         | 
| 127 | 
            +
                def load_plugin(plugin_name, **options)
         | 
| 128 | 
            +
                  plugin_to_use = plugins.find { |plugin| plugin.name == plugin_name }
         | 
| 129 | 
            +
                  fail PluginNotFound.new(plugin_name) unless plugin_to_use
         | 
| 130 | 
            +
                  vputs "Using plugin: #{plugin_name}"
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                  plugin_to_use.load!(options)
         | 
| 133 | 
            +
                  loaded_plugins << plugin_to_use
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                  true
         | 
| 136 | 
            +
                end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                private
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                def find_project_root
         | 
| 141 | 
            +
                  if rails?
         | 
| 142 | 
            +
                    ::Rails.root
         | 
| 143 | 
            +
                  else
         | 
| 144 | 
            +
                    root_by_git || root_by_lib_dir
         | 
| 145 | 
            +
                  end
         | 
| 146 | 
            +
                end
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                def root_by_git
         | 
| 149 | 
            +
                  _stdin, stdout, _stderr = Open3.popen3('git rev-parse --show-toplevel')
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                  stdout.gets.strip
         | 
| 152 | 
            +
                end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                def root_by_lib_dir
         | 
| 155 | 
            +
                  cwd = Pathname.new(Dir.pwd)
         | 
| 156 | 
            +
                  root = nil
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                  cwd.ascend do |dir|
         | 
| 159 | 
            +
                    lib_dir = File.join(dir.to_s, 'lib')
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                    if dir.children.find { |c| c.to_s =~ /#{lib_dir}/ && File.exist?(lib_dir) }
         | 
| 162 | 
            +
                      root = dir.to_s
         | 
| 163 | 
            +
                      break
         | 
| 164 | 
            +
                    end
         | 
| 165 | 
            +
                  end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                  root
         | 
| 168 | 
            +
                end
         | 
| 169 | 
            +
              end
         | 
| 170 | 
            +
            end
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            require 'hairballs/ext/kernel_vputs'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            class Hairballs
         | 
| 2 4 | 
             
              # Helpers specifying and requiring dependencies for Themes and Plugins.
         | 
| 3 5 | 
             
              module LibraryHelpers
         | 
| @@ -5,14 +7,11 @@ class Hairballs | |
| 5 7 | 
             
                def libraries(libs=nil)
         | 
| 6 8 | 
             
                  return @libraries if @libraries && libs.nil?
         | 
| 7 9 |  | 
| 8 | 
            -
                  @libraries =  | 
| 9 | 
            -
             | 
| 10 | 
            -
                   | 
| 11 | 
            -
                     | 
| 12 | 
            -
                      "Block must return an Array but returned #{@libraries}."
         | 
| 10 | 
            +
                  @libraries = if libs
         | 
| 11 | 
            +
                    libs
         | 
| 12 | 
            +
                  else
         | 
| 13 | 
            +
                    yield([])
         | 
| 13 14 | 
             
                  end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                  @libraries
         | 
| 16 15 | 
             
                end
         | 
| 17 16 |  | 
| 18 17 | 
             
                # Requires #libraries on load.  If they're not installed, install them.  If
         | 
| @@ -43,10 +42,14 @@ class Hairballs | |
| 43 42 | 
             
                  end
         | 
| 44 43 | 
             
                end
         | 
| 45 44 |  | 
| 45 | 
            +
                # Path to the highest version of the gem with the given gem.
         | 
| 46 | 
            +
                #
         | 
| 47 | 
            +
                # @param [String] gem_name
         | 
| 48 | 
            +
                # @return [String]
         | 
| 46 49 | 
             
                def find_latest_gem(gem_name)
         | 
| 47 50 | 
             
                  the_gem = Dir.glob("#{Gem.dir}/gems/#{gem_name}-*")
         | 
| 48 51 |  | 
| 49 | 
            -
                  the_gem.empty? ? nil : the_gem. | 
| 52 | 
            +
                  the_gem.empty? ? nil : the_gem.sort.last
         | 
| 50 53 | 
             
                end
         | 
| 51 54 |  | 
| 52 55 | 
             
                # Add all gems in the global gemset to the $LOAD_PATH so they can be used
         | 
    
        data/lib/hairballs/plugin.rb
    CHANGED
    
    | @@ -1,4 +1,5 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require 'hairballs/exceptions'
         | 
| 2 | 
            +
            require 'hairballs/library_helpers'
         | 
| 2 3 |  | 
| 3 4 | 
             
            class Hairballs
         | 
| 4 5 | 
             
              # Plugins provide means for adding functionality to your IRB sessions.  They
         | 
| @@ -63,12 +64,12 @@ class Hairballs | |
| 63 64 |  | 
| 64 65 | 
             
                  require_libraries
         | 
| 65 66 |  | 
| 66 | 
            -
                   | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
                     | 
| 70 | 
            -
             | 
| 71 | 
            -
                     | 
| 67 | 
            +
                  return unless @on_load
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  if @on_load.kind_of?(Proc)
         | 
| 70 | 
            +
                    @on_load.call
         | 
| 71 | 
            +
                  else
         | 
| 72 | 
            +
                    fail PluginLoadFailure, self.name
         | 
| 72 73 | 
             
                  end
         | 
| 73 74 | 
             
                end
         | 
| 74 75 | 
             
              end
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require 'hairballs'
         | 
| 2 2 |  | 
| 3 3 | 
             
            # Adds the ability to tab-complete files that are in the current directory.
         | 
| 4 4 | 
             
            #
         | 
| @@ -9,10 +9,13 @@ require_relative '../../hairballs' | |
| 9 9 | 
             
            #     # Will complete like this...
         | 
| 10 10 | 
             
            #     irb> File.read("README.md"
         | 
| 11 11 | 
             
            #
         | 
| 12 | 
            -
             | 
| 12 | 
            +
            # The +completion_append_character+ is really a Readline option that tells it
         | 
| 13 | 
            +
            # what to do when you tab-complete a term. It's set to not add anything to the
         | 
| 14 | 
            +
            # completed term, but you may find it suits you better to append a single space.
         | 
| 15 | 
            +
            Hairballs.add_plugin(:tab_completion_for_files, completion_append_character: nil) do |plugin|
         | 
| 13 16 | 
             
              plugin.on_load do
         | 
| 14 17 | 
             
                Hairballs.completion_procs << proc do |string|
         | 
| 15 | 
            -
                  Dir['*'].grep(/^#{Regexp.escape(string)} | 
| 18 | 
            +
                  Dir[string + '*'].grep(/^#{Regexp.escape(string)}/)
         | 
| 16 19 | 
             
                end
         | 
| 17 20 |  | 
| 18 21 | 
             
                if defined? ::IRB::InputCompletor::CompletionProc
         | 
| @@ -25,11 +28,12 @@ Hairballs.add_plugin(:tab_completion_for_files) do |plugin| | |
| 25 28 | 
             
                  end.flatten.uniq
         | 
| 26 29 | 
             
                end
         | 
| 27 30 |  | 
| 28 | 
            -
                if Readline.respond_to?( | 
| 29 | 
            -
                  Readline.basic_word_break_characters | 
| 31 | 
            +
                if Readline.respond_to?(:basic_word_break_characters=)
         | 
| 32 | 
            +
                  original_breaks = Readline.basic_word_break_characters
         | 
| 33 | 
            +
                  Readline.basic_word_break_characters = " \"'#{original_breaks}"
         | 
| 30 34 | 
             
                end
         | 
| 31 35 |  | 
| 32 | 
            -
                Readline.completion_append_character =  | 
| 36 | 
            +
                Readline.completion_append_character = plugin.completion_append_character
         | 
| 33 37 | 
             
                Readline.completion_proc = completion_proc
         | 
| 34 38 | 
             
              end
         | 
| 35 39 | 
             
            end
         | 
    
        data/lib/hairballs/theme.rb
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 1 | 
            +
            require 'hairballs/library_helpers'
         | 
| 2 | 
            +
            require 'hairballs/prompt'
         | 
| 3 3 |  | 
| 4 4 | 
             
            class Hairballs
         | 
| 5 5 | 
             
              # Themes primarily provide a means for customizing the look of your IRB
         | 
| @@ -10,7 +10,7 @@ class Hairballs | |
| 10 10 | 
             
              # +Hairballs.add_theme()+ and +Hairballs.use_theme()+ should cover most use
         | 
| 11 11 | 
             
              # cases.
         | 
| 12 12 | 
             
              class Theme
         | 
| 13 | 
            -
                include LibraryHelpers
         | 
| 13 | 
            +
                include Hairballs::LibraryHelpers
         | 
| 14 14 |  | 
| 15 15 | 
             
                # Just an identifier for the Theme.  Don't name two themes the same
         | 
| 16 16 | 
             
                # name--that will cause problems.
         | 
| @@ -97,7 +97,6 @@ class Hairballs | |
| 97 97 | 
             
                end
         | 
| 98 98 |  | 
| 99 99 | 
             
                def set_up_pry_printer
         | 
| 100 | 
            -
                  puts "@pompt return format: #{@prompt.return_format}"
         | 
| 101 100 | 
             
                  if @prompt.return_format
         | 
| 102 101 | 
             
                    Pry.config.print = proc do |output, value|
         | 
| 103 102 | 
             
                      output.printf @prompt.return_format, value.inspect
         | 
| @@ -1,14 +1,14 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require 'hairballs'
         | 
| 2 2 |  | 
| 3 3 | 
             
            Hairballs.add_theme(:turboladen) do |theme|
         | 
| 4 | 
            -
              theme.libraries do
         | 
| 5 | 
            -
                libs_to_require  | 
| 4 | 
            +
              theme.libraries do |libs_to_require|
         | 
| 5 | 
            +
                libs_to_require += %w(
         | 
| 6 6 | 
             
                  irb/completion
         | 
| 7 7 | 
             
                  looksee
         | 
| 8 8 | 
             
                  colorize
         | 
| 9 9 | 
             
                )
         | 
| 10 10 |  | 
| 11 | 
            -
                libs_to_require  | 
| 11 | 
            +
                libs_to_require +=
         | 
| 12 12 | 
             
                  case RUBY_PLATFORM
         | 
| 13 13 | 
             
                  when /mswin32|mingw32/
         | 
| 14 14 | 
             
                    %w(win32console)
         | 
| @@ -1,14 +1,14 @@ | |
| 1 | 
            -
             | 
| 1 | 
            +
            require 'hairballs'
         | 
| 2 2 |  | 
| 3 3 | 
             
            Hairballs.add_theme(:turboladen_rails) do |theme|
         | 
| 4 | 
            -
              theme.libraries do
         | 
| 5 | 
            -
                libs_to_require  | 
| 4 | 
            +
              theme.libraries do |libs_to_require|
         | 
| 5 | 
            +
                libs_to_require += %w(
         | 
| 6 6 | 
             
                  irb/completion
         | 
| 7 7 | 
             
                  looksee
         | 
| 8 8 | 
             
                  colorize
         | 
| 9 9 | 
             
                )
         | 
| 10 10 |  | 
| 11 | 
            -
                libs_to_require  | 
| 11 | 
            +
                libs_to_require +=
         | 
| 12 12 | 
             
                  case RUBY_PLATFORM
         | 
| 13 13 | 
             
                  when /mswin32|mingw32/
         | 
| 14 14 | 
             
                    %w(win32console)
         | 
    
        data/lib/hairballs/version.rb
    CHANGED
    
    
    
        data/lib/hairballs.rb
    CHANGED
    
    | @@ -1,113 +1,33 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
            require_relative 'hairballs/plugin'
         | 
| 5 | 
            -
            require_relative 'hairballs/version'
         | 
| 1 | 
            +
            require 'forwardable'
         | 
| 2 | 
            +
            require 'hairballs/version'
         | 
| 3 | 
            +
            require 'hairballs/configuration'
         | 
| 6 4 |  | 
| 7 5 | 
             
            # Home of the Hairballs DSL for defining and using Themes and Plugins.
         | 
| 8 6 | 
             
            class Hairballs
         | 
| 9 | 
            -
               | 
| 10 | 
            -
             | 
| 11 | 
            -
                 | 
| 12 | 
            -
             | 
| 13 | 
            -
                # @return [Array<Hairballs::Theme>]
         | 
| 14 | 
            -
                def themes
         | 
| 15 | 
            -
                  @themes ||= []
         | 
| 16 | 
            -
                end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                # Builds a new Hairballs::Theme and adds it to the list of `.themes` that
         | 
| 19 | 
            -
                # can be used.
         | 
| 20 | 
            -
                #
         | 
| 21 | 
            -
                # @param name [Symbol] Name to give the new Theme.
         | 
| 22 | 
            -
                # @return [Theme]
         | 
| 23 | 
            -
                def add_theme(name)
         | 
| 24 | 
            -
                  theme = Theme.new(name)
         | 
| 25 | 
            -
                  yield theme
         | 
| 26 | 
            -
                  themes << theme
         | 
| 27 | 
            -
                  vputs "Added theme: #{name}"
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                  theme
         | 
| 30 | 
            -
                end
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                # Tells IRB to use the Hairballs::Theme of +theme_name+.
         | 
| 33 | 
            -
                #
         | 
| 34 | 
            -
                # @param theme_name [Symbol] The name of the Theme to use/switch to.
         | 
| 35 | 
            -
                def use_theme(theme_name)
         | 
| 36 | 
            -
                  switch_to = themes.find { |theme| theme.name == theme_name }
         | 
| 37 | 
            -
                  fail ThemeUseFailure.new(theme_name) unless switch_to
         | 
| 38 | 
            -
                  vputs "Switched to theme: #{theme_name}"
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                  switch_to.use!
         | 
| 41 | 
            -
                  @current_theme = switch_to
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                  true
         | 
| 44 | 
            -
                end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                # All Hairballs::Plugins available to be loaded.
         | 
| 47 | 
            -
                #
         | 
| 48 | 
            -
                # @return [Array<Hairballs::Plugin>]
         | 
| 49 | 
            -
                def plugins
         | 
| 50 | 
            -
                  @plugins ||= []
         | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                # All Hairballs::Plugins that have been loaded.
         | 
| 54 | 
            -
                #
         | 
| 55 | 
            -
                # @return [Array<Hairballs::Plugin>]
         | 
| 56 | 
            -
                def loaded_plugins
         | 
| 57 | 
            -
                  @loaded_plugins ||= []
         | 
| 58 | 
            -
                end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                # Builds a new Hairballs::Plugin and adds it to thelist of `.plugins` that
         | 
| 61 | 
            -
                # can be used.
         | 
| 62 | 
            -
                #
         | 
| 63 | 
            -
                # @param name [Symbol]
         | 
| 64 | 
            -
                # @param options [Hash] Plugin-dependent options to define.  These get
         | 
| 65 | 
            -
                #   passed along the the Hairballs::Plugin object and are used as attributes
         | 
| 66 | 
            -
                #   of the plugin.
         | 
| 67 | 
            -
                def add_plugin(name, **options)
         | 
| 68 | 
            -
                  plugin = Plugin.new(name, options)
         | 
| 69 | 
            -
                  yield plugin
         | 
| 70 | 
            -
                  plugins << plugin
         | 
| 71 | 
            -
                  vputs "Added plugin: #{name}"
         | 
| 72 | 
            -
             | 
| 73 | 
            -
                  plugin
         | 
| 74 | 
            -
                end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                # Searches for the Hairballs::Plugin by the +plugin_name+, then loads it.
         | 
| 77 | 
            -
                # Raises
         | 
| 78 | 
            -
                # @param plugin_name [Symbol]
         | 
| 79 | 
            -
                def load_plugin(plugin_name, **options)
         | 
| 80 | 
            -
                  plugin_to_use = plugins.find { |plugin| plugin.name == plugin_name }
         | 
| 81 | 
            -
                  fail PluginNotFound.new(plugin_name) unless plugin_to_use
         | 
| 82 | 
            -
                  vputs "Using plugin: #{plugin_name}"
         | 
| 7 | 
            +
              # @return [Hairballs::Configuration]
         | 
| 8 | 
            +
              def self.config
         | 
| 9 | 
            +
                @@config ||= Hairballs::Configuration.new
         | 
| 10 | 
            +
              end
         | 
| 83 11 |  | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 12 | 
            +
              class << self
         | 
| 13 | 
            +
                extend Forwardable
         | 
| 86 14 |  | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 15 | 
            +
                def_delegators :config,
         | 
| 16 | 
            +
                  :themes,
         | 
| 17 | 
            +
                  :add_theme,
         | 
| 18 | 
            +
                  :current_theme,
         | 
| 19 | 
            +
                  :use_theme,
         | 
| 89 20 |  | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
                  @project_name ||= File.basename(Dir.pwd)
         | 
| 95 | 
            -
                end
         | 
| 21 | 
            +
                  :plugins,
         | 
| 22 | 
            +
                  :load_plugin,
         | 
| 23 | 
            +
                  :loaded_plugins,
         | 
| 24 | 
            +
                  :add_plugin,
         | 
| 96 25 |  | 
| 97 | 
            -
             | 
| 98 | 
            -
                #
         | 
| 99 | 
            -
                # @return [Boolean]
         | 
| 100 | 
            -
                def rails?
         | 
| 101 | 
            -
                  ENV.has_key?('RAILS_ENV') || !!defined?(Rails)
         | 
| 102 | 
            -
                end
         | 
| 26 | 
            +
                  :completion_procs,
         | 
| 103 27 |  | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 107 | 
            -
             | 
| 108 | 
            -
                # @return [Array<Proc>]
         | 
| 109 | 
            -
                def completion_procs
         | 
| 110 | 
            -
                  @completion_procs ||= []
         | 
| 111 | 
            -
                end
         | 
| 28 | 
            +
                  :project_name,
         | 
| 29 | 
            +
                  :project_root,
         | 
| 30 | 
            +
                  :version,
         | 
| 31 | 
            +
                  :rails?
         | 
| 112 32 | 
             
              end
         | 
| 113 33 | 
             
            end
         | 
| @@ -0,0 +1,195 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'hairballs/configuration'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            RSpec.describe Hairballs::Configuration do
         | 
| 5 | 
            +
              subject(:config) { described_class.new }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              describe '#themes' do
         | 
| 8 | 
            +
                subject { config.themes }
         | 
| 9 | 
            +
                it { is_expected.to be_an Array }
         | 
| 10 | 
            +
                it { is_expected.to be_empty }
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              describe '#add_theme' do
         | 
| 14 | 
            +
                let(:theme) { double 'Hairballs::Theme' }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                context 'block given and name param is a Symbol' do
         | 
| 17 | 
            +
                  before do
         | 
| 18 | 
            +
                    expect(Hairballs::Theme).to receive(:new).with(:test).and_return theme
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  it 'yields the Theme' do
         | 
| 22 | 
            +
                    expect { |b| subject.add_theme(:test, &b) }.to yield_with_args(theme)
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  it 'adds the Theme to @themes' do
         | 
| 26 | 
            +
                    expect(subject.themes).to receive(:<<).with(theme)
         | 
| 27 | 
            +
                    subject.add_theme(:test) { |_| }
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  it 'returns the Theme' do
         | 
| 31 | 
            +
                    expect(subject.add_theme(:test) { |_| }).to eq theme
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                context 'no block given' do
         | 
| 36 | 
            +
                  before do
         | 
| 37 | 
            +
                    allow(Hairballs::Theme).to receive(:new).and_return theme
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  it 'raises a LocalJumpError' do
         | 
| 41 | 
            +
                    expect { subject.add_theme(:test) }.to raise_exception(LocalJumpError)
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
              describe '#use_theme' do
         | 
| 47 | 
            +
                let(:theme) { double 'Hairballs::Theme', name: :test }
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                context 'theme_name represents an added theme' do
         | 
| 50 | 
            +
                  before do
         | 
| 51 | 
            +
                    expect(subject.themes).to receive(:find).and_return theme
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                  it 'does not raise a ThemeUseFailure' do
         | 
| 55 | 
            +
                    allow(theme).to receive(:use!)
         | 
| 56 | 
            +
                    expect { subject.use_theme(:test) }.to_not raise_exception
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                  it 'tells the theme to #use!' do
         | 
| 60 | 
            +
                    expect(theme).to receive(:use!)
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    subject.use_theme(:test)
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                  it 'sets @current_theme to the new theme' do
         | 
| 66 | 
            +
                    allow(theme).to receive(:use!)
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    expect { subject.use_theme(:test) }.
         | 
| 69 | 
            +
                      to change { subject.instance_variable_get(:@current_theme) }.
         | 
| 70 | 
            +
                      to(theme)
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                context 'theme_name does not represent an added theme' do
         | 
| 75 | 
            +
                  it 'raises a ThemeUseFailure' do
         | 
| 76 | 
            +
                    expect(subject.themes).to receive(:find).and_return nil
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                    expect do
         | 
| 79 | 
            +
                      subject.use_theme(:meow)
         | 
| 80 | 
            +
                    end.to raise_exception(Hairballs::ThemeUseFailure)
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
              describe '#plugins' do
         | 
| 86 | 
            +
                subject { config.plugins }
         | 
| 87 | 
            +
                it { is_expected.to be_an Array }
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              describe '#loaded_plugins' do
         | 
| 91 | 
            +
                subject { config.loaded_plugins }
         | 
| 92 | 
            +
                it { is_expected.to be_an Array }
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
              describe '#add_plugin' do
         | 
| 96 | 
            +
                let(:plugin) { double 'Hairballs::Plugin' }
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                context 'block given and name param is a Symbol' do
         | 
| 99 | 
            +
                  before do
         | 
| 100 | 
            +
                    expect(Hairballs::Plugin).to receive(:new).with(:test, {}).and_return plugin
         | 
| 101 | 
            +
                  end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  it 'yields the Plugin' do
         | 
| 104 | 
            +
                    expect { |b| subject.add_plugin(:test, &b) }.to yield_with_args(plugin)
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  it 'adds the Plugin to @plugins' do
         | 
| 108 | 
            +
                    expect(subject.plugins).to receive(:<<).with(plugin)
         | 
| 109 | 
            +
                    subject.add_plugin(:test) { |_| }
         | 
| 110 | 
            +
                  end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                  it 'returns the Plugin' do
         | 
| 113 | 
            +
                    expect(subject.add_plugin(:test) { |_| }).to eq plugin
         | 
| 114 | 
            +
                  end
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                context 'no block given' do
         | 
| 118 | 
            +
                  before do
         | 
| 119 | 
            +
                    allow(Hairballs::Plugin).to receive(:new).and_return plugin
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                  it 'raises a LocalJumpError' do
         | 
| 123 | 
            +
                    expect { subject.add_plugin(:test) }.to raise_exception(LocalJumpError)
         | 
| 124 | 
            +
                  end
         | 
| 125 | 
            +
                end
         | 
| 126 | 
            +
              end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
              describe '#load_plugin' do
         | 
| 129 | 
            +
                let(:plugin) { double 'Hairballs::Plugin', name: :test }
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                context 'theme_name represents an added plugin' do
         | 
| 132 | 
            +
                  before do
         | 
| 133 | 
            +
                    expect(subject.plugins).to receive(:find).and_return plugin
         | 
| 134 | 
            +
                  end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                  it 'does not raise an exception' do
         | 
| 137 | 
            +
                    allow(plugin).to receive(:load!)
         | 
| 138 | 
            +
             | 
| 139 | 
            +
                    expect do
         | 
| 140 | 
            +
                      subject.load_plugin(:test)
         | 
| 141 | 
            +
                    end.to_not raise_exception
         | 
| 142 | 
            +
                  end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                  it 'tells the plugin to #load!' do
         | 
| 145 | 
            +
                    expect(plugin).to receive(:load!)
         | 
| 146 | 
            +
                    subject.load_plugin(:test)
         | 
| 147 | 
            +
                  end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  it 'updates @loaded_plugins with the new theme' do
         | 
| 150 | 
            +
                    allow(plugin).to receive(:load!)
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                    expect { subject.load_plugin(:test) }.
         | 
| 153 | 
            +
                      to change { subject.loaded_plugins.size }.
         | 
| 154 | 
            +
                      by(1)
         | 
| 155 | 
            +
                  end
         | 
| 156 | 
            +
                end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                context 'plugin_name does not represent an added plugin' do
         | 
| 159 | 
            +
                  it 'raises a PluginNotFound' do
         | 
| 160 | 
            +
                    expect do
         | 
| 161 | 
            +
                      subject.load_plugin(:meow)
         | 
| 162 | 
            +
                    end.to raise_exception(Hairballs::PluginNotFound)
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
                end
         | 
| 165 | 
            +
              end
         | 
| 166 | 
            +
             | 
| 167 | 
            +
              describe '.project_name' do
         | 
| 168 | 
            +
                subject { config.project_name }
         | 
| 169 | 
            +
                it { is_expected.to eq 'hairballs' }
         | 
| 170 | 
            +
              end
         | 
| 171 | 
            +
             | 
| 172 | 
            +
              describe '.project_root' do
         | 
| 173 | 
            +
                before do
         | 
| 174 | 
            +
                  allow(Dir).to receive(:pwd).and_return '/meow/hairballs'
         | 
| 175 | 
            +
                end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                subject { config.project_name }
         | 
| 178 | 
            +
              end
         | 
| 179 | 
            +
             | 
| 180 | 
            +
              describe '.rails?' do
         | 
| 181 | 
            +
                subject { config.rails? }
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                context 'not using Rails' do
         | 
| 184 | 
            +
                  it { is_expected.to eq false }
         | 
| 185 | 
            +
                end
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                context 'using Rails' do
         | 
| 188 | 
            +
                  context 'RAILS_ENV is defined' do
         | 
| 189 | 
            +
                    before { ENV['RAILS_ENV'] = 'blargh' }
         | 
| 190 | 
            +
                    after { ENV.delete('RAILS_ENV') }
         | 
| 191 | 
            +
                    it { is_expected.to eq true }
         | 
| 192 | 
            +
                  end
         | 
| 193 | 
            +
                end
         | 
| 194 | 
            +
              end
         | 
| 195 | 
            +
            end
         | 
| @@ -0,0 +1,72 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'hairballs/library_helpers'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            RSpec.describe Hairballs::LibraryHelpers do
         | 
| 5 | 
            +
              subject { Object.new.extend described_class }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              describe '#libraries' do
         | 
| 8 | 
            +
                context 'block given' do
         | 
| 9 | 
            +
                  it 'yields an empty array' do
         | 
| 10 | 
            +
                    expect { |b| subject.libraries(&b) }.to yield_with_args([])
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  it 'allows adding to the yielded array' do
         | 
| 14 | 
            +
                    expect {
         | 
| 15 | 
            +
                      subject.libraries do |libs|
         | 
| 16 | 
            +
                        libs << 'meow'
         | 
| 17 | 
            +
                      end
         | 
| 18 | 
            +
                    }.to change { subject.instance_variable_get(:@libraries) }.
         | 
| 19 | 
            +
                    from(nil).to(['meow'])
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                context 'block not given' do
         | 
| 24 | 
            +
                  it 'sets @libraries to the given param' do
         | 
| 25 | 
            +
                    expect {
         | 
| 26 | 
            +
                      subject.libraries(['meow'])
         | 
| 27 | 
            +
                    }.to change { subject.instance_variable_get(:@libraries) }.
         | 
| 28 | 
            +
                    from(nil).to(['meow'])
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                context 'block AND param given' do
         | 
| 33 | 
            +
                  it 'sets @libraries to the param value' do
         | 
| 34 | 
            +
                    expect {
         | 
| 35 | 
            +
                      subject.libraries(['meow'])
         | 
| 36 | 
            +
                    }.to change { subject.instance_variable_get(:@libraries) }.
         | 
| 37 | 
            +
                    from(nil).to(['meow'])
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              describe '#require_libraries' do
         | 
| 43 | 
            +
                context '@libraries is nil' do
         | 
| 44 | 
            +
                  it 'returns nil' do
         | 
| 45 | 
            +
                    expect(subject.require_libraries).to be_nil
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                context '@libraries is not nil' do
         | 
| 50 | 
            +
                  before do
         | 
| 51 | 
            +
                    subject.instance_variable_set(:@libraries, %w(one))
         | 
| 52 | 
            +
                    allow(subject).to receive(:vputs)
         | 
| 53 | 
            +
                    Hairballs.define_singleton_method(:rails?) { nil }
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                  context 'libraries are not installed' do
         | 
| 57 | 
            +
                    it 'tries two times to require then Gem.install' do
         | 
| 58 | 
            +
                      expect(subject).to receive(:require).with('one').exactly(2).times.and_raise LoadError
         | 
| 59 | 
            +
                      expect(Gem).to receive(:install).with('one').exactly(1).times
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                      expect { subject.require_libraries }.to raise_exception LoadError
         | 
| 62 | 
            +
                    end
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
              end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
              describe '#find_latest_gem' do
         | 
| 68 | 
            +
                it 'returns the path to the latest version of the gem' do
         | 
| 69 | 
            +
                  expect(subject.find_latest_gem('rake')).to match %r{gems/rake}
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
            end
         | 
| @@ -0,0 +1,72 @@ | |
| 1 | 
            +
            require 'spec_helper'
         | 
| 2 | 
            +
            require 'hairballs/plugin'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            RSpec.describe Hairballs::Plugin do
         | 
| 5 | 
            +
              subject { described_class.new('test', one: 1, two: 2) }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              describe '#initialize' do
         | 
| 8 | 
            +
                context 'with attributes' do
         | 
| 9 | 
            +
                  it 'defines getters and setters for each attribute' do
         | 
| 10 | 
            +
                    expect(subject.one).to eq 1
         | 
| 11 | 
            +
                    subject.one = 1.1
         | 
| 12 | 
            +
                    expect(subject.one).to eq 1.1
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    expect(subject.two).to eq 2
         | 
| 15 | 
            +
                    subject.two = 2.2
         | 
| 16 | 
            +
                    expect(subject.two).to eq 2.2
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              describe '#on_load' do
         | 
| 22 | 
            +
                let(:the_block) { proc { puts 'hi' } }
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                it 'stores the given block' do
         | 
| 25 | 
            +
                  expect {
         | 
| 26 | 
            +
                    subject.on_load(&the_block)
         | 
| 27 | 
            +
                  }.to change { subject.instance_variable_get(:@on_load) }.
         | 
| 28 | 
            +
                  from(nil).to(the_block)
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              describe '#load!' do
         | 
| 33 | 
            +
                context 'with attributes' do
         | 
| 34 | 
            +
                  it 'sets the attributes' do
         | 
| 35 | 
            +
                    expect(subject).to receive(:one=).with('thing one')
         | 
| 36 | 
            +
                    expect(subject).to receive(:two=).with('thing two')
         | 
| 37 | 
            +
                    allow(subject).to receive(:require_libraries)
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                    subject.load! one: 'thing one', two: 'thing two'
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                context 'without attributes' do
         | 
| 44 | 
            +
                  it 'does not set the attributes' do
         | 
| 45 | 
            +
                    expect(subject).to_not receive(:one=)
         | 
| 46 | 
            +
                    expect(subject).to_not receive(:two=)
         | 
| 47 | 
            +
                    allow(subject).to receive(:require_libraries)
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    subject.load!
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                context 'with @on_load set to a Proc' do
         | 
| 54 | 
            +
                  let(:on_load) { double 'Proc', :kind_of? => true }
         | 
| 55 | 
            +
                  before { subject.instance_variable_set(:@on_load, on_load) }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  it 'calls the on_load Proc' do
         | 
| 58 | 
            +
                    expect(on_load).to receive(:call)
         | 
| 59 | 
            +
                    subject.load!
         | 
| 60 | 
            +
                  end
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                context 'with @on_load set to not a Proc' do
         | 
| 64 | 
            +
                  let(:on_load) { double 'Proc', :kind_of? => false }
         | 
| 65 | 
            +
                  before { subject.instance_variable_set(:@on_load, on_load) }
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  it 'raises a PluginLoadFailure' do
         | 
| 68 | 
            +
                    expect { subject.load! }.to raise_exception Hairballs::PluginLoadFailure
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
            end
         | 
    
        data/spec/hairballs_spec.rb
    CHANGED
    
    | @@ -2,184 +2,28 @@ require 'spec_helper' | |
| 2 2 | 
             
            require 'hairballs'
         | 
| 3 3 |  | 
| 4 4 | 
             
            describe Hairballs do
         | 
| 5 | 
            -
              subject { described_class }
         | 
| 5 | 
            +
              subject(:hairballs) { described_class }
         | 
| 6 6 |  | 
| 7 | 
            -
              describe '. | 
| 8 | 
            -
                subject {  | 
| 9 | 
            -
                it { is_expected.to  | 
| 7 | 
            +
              describe '.config' do
         | 
| 8 | 
            +
                subject { hairballs.config }
         | 
| 9 | 
            +
                it { is_expected.to be_a Hairballs::Configuration }
         | 
| 10 10 | 
             
              end
         | 
| 11 11 |  | 
| 12 | 
            -
               | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
                    expect(Hairballs::Theme).to receive(:new).with(:test).and_return theme
         | 
| 17 | 
            -
                  end
         | 
| 12 | 
            +
              it { is_expected.to respond_to(:themes) }
         | 
| 13 | 
            +
              it { is_expected.to respond_to(:current_theme) }
         | 
| 14 | 
            +
              it { is_expected.to respond_to(:add_theme) }
         | 
| 15 | 
            +
              it { is_expected.to respond_to(:use_theme) }
         | 
| 18 16 |  | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 17 | 
            +
              it { is_expected.to respond_to(:plugins) }
         | 
| 18 | 
            +
              it { is_expected.to respond_to(:loaded_plugins) }
         | 
| 19 | 
            +
              it { is_expected.to respond_to(:add_plugin) }
         | 
| 20 | 
            +
              it { is_expected.to respond_to(:load_plugin) }
         | 
| 22 21 |  | 
| 23 | 
            -
             | 
| 24 | 
            -
                    expect(subject.themes).to receive(:<<).with(theme)
         | 
| 25 | 
            -
                    subject.add_theme(:test) { |_| }
         | 
| 26 | 
            -
                  end
         | 
| 22 | 
            +
              it { is_expected.to respond_to(:completion_procs) }
         | 
| 27 23 |  | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
                end
         | 
| 24 | 
            +
              it { is_expected.to respond_to(:project_name) }
         | 
| 25 | 
            +
              it { is_expected.to respond_to(:project_root) }
         | 
| 26 | 
            +
              it { is_expected.to respond_to(:rails?) }
         | 
| 32 27 |  | 
| 33 | 
            -
             | 
| 34 | 
            -
                  before do
         | 
| 35 | 
            -
                    allow(Hairballs::Theme).to receive(:new).and_return theme
         | 
| 36 | 
            -
                  end
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                  it 'raises a LocalJumpError' do
         | 
| 39 | 
            -
                    expect { subject.add_theme(:test) }.to raise_exception(LocalJumpError)
         | 
| 40 | 
            -
                  end
         | 
| 41 | 
            -
                end
         | 
| 42 | 
            -
              end
         | 
| 43 | 
            -
             | 
| 44 | 
            -
              describe '.use_theme' do
         | 
| 45 | 
            -
                let(:theme) { double 'Hairballs::Theme', name: :test }
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                context 'theme_name represents an added theme' do
         | 
| 48 | 
            -
                  before(:example) do
         | 
| 49 | 
            -
                    expect(subject.themes).to receive(:find).and_return theme
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                  it 'does not raise a ThemeUseFailure' do
         | 
| 53 | 
            -
                    allow(theme).to receive(:use!)
         | 
| 54 | 
            -
             | 
| 55 | 
            -
                    expect do
         | 
| 56 | 
            -
                      subject.use_theme(:test)
         | 
| 57 | 
            -
                    end.to_not raise_exception
         | 
| 58 | 
            -
                  end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
                  it 'tells the theme to #use!' do
         | 
| 61 | 
            -
                    expect(theme).to receive(:use!)
         | 
| 62 | 
            -
                    subject.use_theme(:test)
         | 
| 63 | 
            -
                  end
         | 
| 64 | 
            -
             | 
| 65 | 
            -
                  it 'sets @current_theme to the new theme' do
         | 
| 66 | 
            -
                    allow(theme).to receive(:use!)
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                    expect { subject.use_theme(:test) }.
         | 
| 69 | 
            -
                      to change { subject.instance_variable_get(:@current_theme) }.
         | 
| 70 | 
            -
                      to(theme)
         | 
| 71 | 
            -
                  end
         | 
| 72 | 
            -
                end
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                context 'theme_name does not represent an added theme' do
         | 
| 75 | 
            -
                  it 'raises a ThemeUseFailure' do
         | 
| 76 | 
            -
                    expect do
         | 
| 77 | 
            -
                      described_class.use_theme(:meow)
         | 
| 78 | 
            -
                    end.to raise_exception(Hairballs::ThemeUseFailure)
         | 
| 79 | 
            -
                  end
         | 
| 80 | 
            -
                end
         | 
| 81 | 
            -
              end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
              describe '.plugins' do
         | 
| 84 | 
            -
                subject { described_class.plugins }
         | 
| 85 | 
            -
                it { is_expected.to be_an Array }
         | 
| 86 | 
            -
              end
         | 
| 87 | 
            -
             | 
| 88 | 
            -
              describe '.loaded_plugins' do
         | 
| 89 | 
            -
                subject { described_class.loaded_plugins }
         | 
| 90 | 
            -
                it { is_expected.to be_an Array }
         | 
| 91 | 
            -
              end
         | 
| 92 | 
            -
             | 
| 93 | 
            -
              describe '.add_plugin' do
         | 
| 94 | 
            -
                let(:plugin) { double 'Hairballs::Plugin' }
         | 
| 95 | 
            -
             | 
| 96 | 
            -
                context 'block given and name param is a Symbol' do
         | 
| 97 | 
            -
                  before do
         | 
| 98 | 
            -
                    expect(Hairballs::Plugin).to receive(:new).with(:test, {}).and_return plugin
         | 
| 99 | 
            -
                  end
         | 
| 100 | 
            -
             | 
| 101 | 
            -
                  it 'yields the Plugin' do
         | 
| 102 | 
            -
                    expect { |b| subject.add_plugin(:test, &b) }.to yield_with_args(plugin)
         | 
| 103 | 
            -
                  end
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                  it 'adds the Plugin to @plugins' do
         | 
| 106 | 
            -
                    expect(subject.plugins).to receive(:<<).with(plugin)
         | 
| 107 | 
            -
                    subject.add_plugin(:test) { |_| }
         | 
| 108 | 
            -
                  end
         | 
| 109 | 
            -
             | 
| 110 | 
            -
                  it 'returns the Plugin' do
         | 
| 111 | 
            -
                    expect(subject.add_plugin(:test) { |_| }).to eq plugin
         | 
| 112 | 
            -
                  end
         | 
| 113 | 
            -
                end
         | 
| 114 | 
            -
             | 
| 115 | 
            -
                context 'no block given' do
         | 
| 116 | 
            -
                  before do
         | 
| 117 | 
            -
                    allow(Hairballs::Plugin).to receive(:new).and_return plugin
         | 
| 118 | 
            -
                  end
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                  it 'raises a LocalJumpError' do
         | 
| 121 | 
            -
                    expect { subject.add_plugin(:test) }.to raise_exception(LocalJumpError)
         | 
| 122 | 
            -
                  end
         | 
| 123 | 
            -
                end
         | 
| 124 | 
            -
              end
         | 
| 125 | 
            -
             | 
| 126 | 
            -
              describe '.load_plugin' do
         | 
| 127 | 
            -
                let(:plugin) { double 'Hairballs::Plugin', name: :test }
         | 
| 128 | 
            -
             | 
| 129 | 
            -
                context 'theme_name represents an added plugin' do
         | 
| 130 | 
            -
                  before(:example) do
         | 
| 131 | 
            -
                    expect(subject.plugins).to receive(:find).and_return plugin
         | 
| 132 | 
            -
                  end
         | 
| 133 | 
            -
             | 
| 134 | 
            -
                  it 'does not raise an exception' do
         | 
| 135 | 
            -
                    allow(plugin).to receive(:load!)
         | 
| 136 | 
            -
             | 
| 137 | 
            -
                    expect do
         | 
| 138 | 
            -
                      subject.load_plugin(:test)
         | 
| 139 | 
            -
                    end.to_not raise_exception
         | 
| 140 | 
            -
                  end
         | 
| 141 | 
            -
             | 
| 142 | 
            -
                  it 'tells the plugin to #load!' do
         | 
| 143 | 
            -
                    expect(plugin).to receive(:load!)
         | 
| 144 | 
            -
                    subject.load_plugin(:test)
         | 
| 145 | 
            -
                  end
         | 
| 146 | 
            -
             | 
| 147 | 
            -
                  it 'updates @loaded_plugins with the new theme' do
         | 
| 148 | 
            -
                    allow(plugin).to receive(:load!)
         | 
| 149 | 
            -
             | 
| 150 | 
            -
                    expect { subject.load_plugin(:test) }.
         | 
| 151 | 
            -
                      to change { subject.loaded_plugins.size }.
         | 
| 152 | 
            -
                      by(1)
         | 
| 153 | 
            -
                  end
         | 
| 154 | 
            -
                end
         | 
| 155 | 
            -
             | 
| 156 | 
            -
                context 'plugin_name does not represent an added plugin' do
         | 
| 157 | 
            -
                  it 'raises a PluginNotFound' do
         | 
| 158 | 
            -
                    expect do
         | 
| 159 | 
            -
                      described_class.load_plugin(:meow)
         | 
| 160 | 
            -
                    end.to raise_exception(Hairballs::PluginNotFound)
         | 
| 161 | 
            -
                  end
         | 
| 162 | 
            -
                end
         | 
| 163 | 
            -
              end
         | 
| 164 | 
            -
             | 
| 165 | 
            -
              describe '.project_name' do
         | 
| 166 | 
            -
                subject { described_class.project_name }
         | 
| 167 | 
            -
                it { is_expected.to eq 'hairballs' }
         | 
| 168 | 
            -
              end
         | 
| 169 | 
            -
             | 
| 170 | 
            -
              describe '.rails?' do
         | 
| 171 | 
            -
                subject { described_class.rails? }
         | 
| 172 | 
            -
             | 
| 173 | 
            -
                context 'not using Rails' do
         | 
| 174 | 
            -
                  it { is_expected.to eq false }
         | 
| 175 | 
            -
                end
         | 
| 176 | 
            -
             | 
| 177 | 
            -
                context 'using Rails' do
         | 
| 178 | 
            -
                  context 'RAILS_ENV is defined' do
         | 
| 179 | 
            -
                    before { ENV['RAILS_ENV'] = 'blargh' }
         | 
| 180 | 
            -
                    after { ENV.delete('RAILS_ENV') }
         | 
| 181 | 
            -
                    it { is_expected.to eq true }
         | 
| 182 | 
            -
                  end
         | 
| 183 | 
            -
                end
         | 
| 184 | 
            -
              end
         | 
| 28 | 
            +
              it { is_expected.to respond_to(:version) }
         | 
| 185 29 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: hairballs
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0 | 
| 4 | 
            +
              version: 0.1.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Steve Loveless
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2015-02-19 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -52,7 +52,7 @@ dependencies: | |
| 52 52 | 
             
                - - "~>"
         | 
| 53 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 54 54 | 
             
                    version: '3.1'
         | 
| 55 | 
            -
            description:  | 
| 55 | 
            +
            description: Like oh-my-zsh, but for IRB.
         | 
| 56 56 | 
             
            email:
         | 
| 57 57 | 
             
            - steve.loveless@gmail.com
         | 
| 58 58 | 
             
            executables: []
         | 
| @@ -68,6 +68,7 @@ files: | |
| 68 68 | 
             
            - Rakefile
         | 
| 69 69 | 
             
            - hairballs.gemspec
         | 
| 70 70 | 
             
            - lib/hairballs.rb
         | 
| 71 | 
            +
            - lib/hairballs/configuration.rb
         | 
| 71 72 | 
             
            - lib/hairballs/exceptions.rb
         | 
| 72 73 | 
             
            - lib/hairballs/ext/kernel_vputs.rb
         | 
| 73 74 | 
             
            - lib/hairballs/library_helpers.rb
         | 
| @@ -86,6 +87,10 @@ files: | |
| 86 87 | 
             
            - lib/hairballs/themes/turboladen.rb
         | 
| 87 88 | 
             
            - lib/hairballs/themes/turboladen_rails.rb
         | 
| 88 89 | 
             
            - lib/hairballs/version.rb
         | 
| 90 | 
            +
            - spec/hairballs/configuration_spec.rb
         | 
| 91 | 
            +
            - spec/hairballs/library_helpers_spec.rb
         | 
| 92 | 
            +
            - spec/hairballs/plugin_spec.rb
         | 
| 93 | 
            +
            - spec/hairballs/theme_spec.rb
         | 
| 89 94 | 
             
            - spec/hairballs_spec.rb
         | 
| 90 95 | 
             
            - spec/spec_helper.rb
         | 
| 91 96 | 
             
            homepage: https://github.com/turboladen/hairballs
         | 
| @@ -108,11 +113,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 108 113 | 
             
                  version: '0'
         | 
| 109 114 | 
             
            requirements: []
         | 
| 110 115 | 
             
            rubyforge_project: 
         | 
| 111 | 
            -
            rubygems_version: 2.2. | 
| 116 | 
            +
            rubygems_version: 2.2.2
         | 
| 112 117 | 
             
            signing_key: 
         | 
| 113 118 | 
             
            specification_version: 4
         | 
| 114 119 | 
             
            summary: Like oh-my-zsh, but for IRB.
         | 
| 115 120 | 
             
            test_files:
         | 
| 121 | 
            +
            - spec/hairballs/configuration_spec.rb
         | 
| 122 | 
            +
            - spec/hairballs/library_helpers_spec.rb
         | 
| 123 | 
            +
            - spec/hairballs/plugin_spec.rb
         | 
| 124 | 
            +
            - spec/hairballs/theme_spec.rb
         | 
| 116 125 | 
             
            - spec/hairballs_spec.rb
         | 
| 117 126 | 
             
            - spec/spec_helper.rb
         | 
| 118 127 | 
             
            has_rdoc: 
         |