hairballs 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6f595d5cee9832427199aed6d743fa45841ba0f4
4
- data.tar.gz: d9b4e863b96a0916fa18b213b42928cfa990457f
3
+ metadata.gz: d9c07d71797efa04ae268dab627d876ec9beab89
4
+ data.tar.gz: 68a2551742e779b78f0f083589c87a97106fad08
5
5
  SHA512:
6
- metadata.gz: ba2513e8c762e7bb9c58fa08309833a083b50374a61723c8386c08ee76af1a4b6a0214dc095c7f456fdc3dc616886eced84cff2ab53b0c91392e44eef8080aa9
7
- data.tar.gz: ffa35bc7c5760a6874594fc50605baf34334292dabaa78d3a30f1e908318613c0d5b68be606e5fccae843632d3eecad77b3936119a6096621e16b67c377c3b6f
6
+ metadata.gz: 63b2faef4e1ec3e6f5afcbbd0197884e7da1c959cb37081efba7bb813f4a6359ce8e19ae2cf3d2a6c4009fff853ec43a9069a4279f754f71540bea016aff5693
7
+ data.tar.gz: aed0e385878f195ef71130c84761fcf38d23bb949d80c114270c9a456e33ad76490769b35992a98fa0d78f45828ed4b398327574563f802bcc0c83687464b632
data/.gitignore CHANGED
@@ -14,3 +14,7 @@
14
14
  mkmf.log
15
15
 
16
16
  tags
17
+
18
+ *.gem
19
+
20
+ .byebug_history
data/.rubocop.yml CHANGED
@@ -16,6 +16,12 @@ Style/Documentation:
16
16
  Style/DotPosition:
17
17
  Enabled: false
18
18
 
19
+ Style/PercentLiteralDelimiters:
20
+ PreferredDelimiters:
21
+ '%i': '[]'
22
+ '%w': '[]'
23
+ '%W': '[]'
24
+
19
25
  Style/RescueModifier:
20
26
  Exclude:
21
27
  - lib/hairballs/plugins/colorize_json.rb
data/.travis.yml CHANGED
@@ -1,3 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - ruby-2.2.0
4
+ before_install:
5
+ - gem install bundler
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in hairballs.gemspec
4
4
  gemspec
5
+
6
+ gem 'rake', group: :test
data/History.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Change Log
2
2
 
3
+ ## [unreleased] / yyyy-mm-dd
4
+
5
+ ### Improvements
6
+
7
+ * For `Plugin`s, only try to require libraries if some are given for the plugin.
8
+ * Changed `quick_benchmark` default to 20 iterations (from 100).
9
+ * Changed `Hairballs::LibraryHelpers` to use Fibers instead of Threads for
10
+ installing dependecies. Threaded installing was proving to be problematic.
11
+
12
+ ### Bug Fixes
13
+
14
+ * Removed `Prompt#auto_indent`; it never worked. To do auto-indenting, just use
15
+ `IRB.conf[:AUTO_INDENT]` directly.
16
+ * Fixed incorrect uses of Yard.
17
+
3
18
  ## 0.1.3 / 2015-07-13
4
19
 
5
20
  ### Improvements
@@ -88,7 +88,7 @@ class Hairballs
88
88
  yield theme
89
89
 
90
90
  themes << theme
91
- vputs "Added theme: #{name}"
91
+ vputs "[config] Added theme: #{name}"
92
92
 
93
93
  theme
94
94
  end
@@ -99,7 +99,7 @@ class Hairballs
99
99
  def use_theme(theme_name)
100
100
  switch_to = themes.find { |theme| theme.name == theme_name }
101
101
  fail ThemeUseFailure, theme_name unless switch_to
102
- vputs "Switched to theme: #{theme_name}"
102
+ vputs "[config] Switched to theme: #{theme_name}"
103
103
 
104
104
  switch_to.use!
105
105
  @current_theme = switch_to
@@ -115,12 +115,17 @@ class Hairballs
115
115
  # passed along the the Hairballs::Plugin object and are used as attributes
116
116
  # of the plugin.
117
117
  def add_plugin(name, **options)
118
+ vputs "[config] Adding plugin: #{name}"
118
119
  plugin = Plugin.new(name, options)
119
120
  yield plugin
120
121
  plugins << plugin
121
- vputs "Added plugin: #{name}"
122
+ vputs "[config] Added plugin: #{name}"
122
123
 
123
124
  plugin
125
+ rescue => ex
126
+ # rubocop:disable Metrics/LineLength
127
+ vputs "[config] Exception adding plugin: #{ex.class}: #{ex.message}\n#{ex.backtrace[0]}"
128
+ # rubocop:enable Metrics/LineLength
124
129
  end
125
130
 
126
131
  # Searches for the Hairballs::Plugin by the +plugin_name+, then loads it.
@@ -129,7 +134,7 @@ class Hairballs
129
134
  def load_plugin(plugin_name, **options)
130
135
  plugin_to_use = plugins.find { |plugin| plugin.name == plugin_name }
131
136
  fail PluginNotFound, plugin_name unless plugin_to_use
132
- vputs "Using plugin: #{plugin_name}"
137
+ vputs "[config] Using plugin: #{plugin_name}"
133
138
 
134
139
  plugin_to_use.load!(options)
135
140
  loaded_plugins << plugin_to_use
@@ -3,6 +3,6 @@ module Kernel
3
3
  # Does a puts only if IRB is in verbose mode.
4
4
  def vputs(*messages)
5
5
  messages.map! { |m| "[Hairballs] #{m}" }
6
- puts(*messages) if defined?(::IRB) && ::IRB.conf[:VERBOSE]
6
+ $stdout.puts(*messages) if defined?(::IRB) && ::IRB.conf[:VERBOSE]
7
7
  end
8
8
  end
@@ -1,4 +1,6 @@
1
+ require 'rubygems/commands/install_command'
1
2
  require 'hairballs/ext/kernel_vputs'
3
+ require 'fiber'
2
4
 
3
5
  class Hairballs
4
6
  # Helpers specifying and requiring dependencies for Themes and Plugins.
@@ -7,11 +9,7 @@ class Hairballs
7
9
  def libraries(libs=nil)
8
10
  return @libraries if @libraries && libs.nil?
9
11
 
10
- @libraries = if libs
11
- libs
12
- else
13
- yield([])
14
- end
12
+ @libraries = libs ? libs : yield([])
15
13
  end
16
14
 
17
15
  # Requires #libraries on load. If they're not installed, install them. If
@@ -19,20 +17,21 @@ class Hairballs
19
17
  def require_libraries
20
18
  return if @libraries.nil?
21
19
 
22
- install_threads = []
23
- require_threads = []
24
- require_queue = Queue.new
20
+ missing_dependencies = []
25
21
 
26
22
  @libraries.each do |lib|
27
23
  begin
28
- vputs "Requiring library: #{lib}"
29
- require lib
24
+ vrequire(lib)
30
25
  rescue LoadError
31
- puts "#{lib} not installed; installing now..."
32
- install_threads << start_install_thread(lib, require_queue)
33
- require_threads << start_require_thread(require_queue)
26
+ # rubocop:disable Metrics/LineLength
27
+ vputs "[**:#{@name}](#{lib}) Unable to require; adding to install list..."
28
+ # rubocop:enable Metrics/LineLength
29
+ missing_dependencies << lib
34
30
  end
35
31
  end
32
+
33
+ requirer = new_dependency_requirer(dependency_installer)
34
+ install_missing_dependencies(missing_dependencies, requirer).resume
36
35
  end
37
36
 
38
37
  # Path to the highest version of the gem with the given gem.
@@ -50,15 +49,23 @@ class Hairballs
50
49
  #
51
50
  # TODO: Use #find_latest_gem for each of #libraries.
52
51
  def do_bundler_extending
52
+ vputs "[**:#{@name}] #do_bundler_extending: #{@libraries}"
53
+
53
54
  if defined?(::Bundler)
55
+ vputs "[**:#{@name}] #do_bundler_extending: Libraries: #{@libraries}"
56
+
54
57
  all_global_gem_paths = Dir.glob("#{Gem.dir}/gems/*")
55
58
 
56
59
  all_global_gem_paths.each do |p|
60
+ next unless @libraries.any? { |l| p.include?(l) }
57
61
  gem_path = "#{p}/lib"
62
+ # rubocop:disable Metrics/LineLength
63
+ vputs "[**:#{@name}] #do_bundler_extending: Adding to $LOAD_PATH: #{gem_path}"
64
+ # rubocop:enable
58
65
  $LOAD_PATH.unshift(gem_path)
59
66
  end
60
67
  else
61
- vputs 'Bundler not defined. Skipping.'
68
+ vputs %([**:#{@name}] #do_bundler_extending: Bundler not defined. Skipping.)
62
69
  end
63
70
  end
64
71
 
@@ -74,7 +81,7 @@ class Hairballs
74
81
  $LOAD_PATH.delete(gem_path)
75
82
  end
76
83
  else
77
- vputs 'Bundler not defined. Skipping.'
84
+ vputs %([**:#{@name}] Bundler not defined. Skipping.)
78
85
  end
79
86
  end
80
87
 
@@ -84,35 +91,83 @@ class Hairballs
84
91
 
85
92
  private
86
93
 
87
- # @param [String] lib Gem to install.
88
- # @param [Queue] require_queue Queue to push library names onto so the
89
- # require thread can do its requiring.
90
- # @return [Thread]
91
- def start_install_thread(lib, require_queue)
92
- Thread.new do
93
- result = Gem.install(lib)
94
-
95
- if result.empty?
96
- puts "Unable to install gem '#{lib}'. Moving on..."
97
- else
98
- require_queue << lib
94
+ # @param lib [String]
95
+ def vrequire(lib)
96
+ vputs "[**:#{@name}](#{lib}) Requiring library..."
97
+ require lib
98
+ vputs "[**:#{@name}](#{lib}) Successfully required library!"
99
+ end
100
+
101
+ # @param deps [Array<String>] Names of the gems to install.
102
+ # @param source [Fiber]
103
+ # @retrun [Fiber]
104
+ def install_missing_dependencies(deps, source)
105
+ Fiber.new do
106
+ deps.each do |lib|
107
+ vputs "[**:#{@name}] #install_missing_dependencies Main dep... #{lib}"
108
+ source.resume(lib)
99
109
  end
100
110
  end
101
111
  end
102
112
 
103
- # @param [Queue] require_queue
104
- # @return [Thread]
105
- def start_require_thread(require_queue)
106
- Thread.new do
107
- lib = require_queue.pop
113
+ # @return [Fiber]
114
+ def dependency_installer
115
+ Fiber.new do |lib|
116
+ loop do
117
+ vputs "[**:#{@name}] #dependency_installer installing #{lib}"
118
+ result = install_gem(lib)
119
+
120
+ vputs "[**:#{@name}] #dependency_installer Gem install of #{lib} done."
121
+ puts "Unable to install gem '#{lib}'. Moving on..." if result > 0
108
122
 
109
- if Hairballs.config.rails?
110
- installed_gem = find_latest_gem(lib)
111
- $LOAD_PATH.unshift("#{installed_gem}/lib")
123
+ lib = Fiber.yield
124
+ vputs "[**:#{@name}] #dependency_installer yield result: #{lib}"
112
125
  end
126
+ end
127
+ end
128
+
129
+ # @param lib [String]
130
+ # @return [Fixnum] Exit code from the Gem::Commands::InstallCommand.
131
+ def install_gem(lib)
132
+ cmd = Gem::Commands::InstallCommand.new
133
+ cmd.handle_options [lib]
134
+ result = 0
135
+
136
+ begin
137
+ cmd.execute
138
+ rescue Gem::SystemExitException, Gem::RemoveFetcher::FetchError => ex
139
+ puts "Got exception during '#{lib}' install: #{ex.class}: #{ex.message}"
140
+ result = ex.exit_code
141
+ end
113
142
 
114
- require lib
115
- end.join
143
+ result
144
+ end
145
+
146
+ # @param [Queue] installer
147
+ # @return [Fiber]
148
+ def new_dependency_requirer(installer)
149
+ Fiber.new do |lib|
150
+ loop do
151
+ vputs "[**:#{@name}] #new_dependency_requirer resumed for #{lib}"
152
+ installer.resume(lib)
153
+ vputs "[**:#{@name}] #new_dependency_requirer requiring lib #{lib}"
154
+
155
+ if Hairballs.config.rails?
156
+ installed_gem = find_latest_gem(lib)
157
+ vputs "[**:#{@name}] #new_dependency_requirer: Gem installed at #{installed_gem}"
158
+ $LOAD_PATH.unshift("#{installed_gem}/lib")
159
+ end
160
+
161
+ begin
162
+ require lib
163
+ rescue LoadError => ex
164
+ puts "Got exception during #{lib} require: #{ex}"
165
+ end
166
+
167
+ vputs %([**:#{@name}] #new_dependency_requirer yielding...)
168
+ lib = Fiber.yield
169
+ end
170
+ end
116
171
  end
117
172
  end
118
173
  end
@@ -62,15 +62,16 @@ class Hairballs
62
62
  send("#{k}=".to_sym, v)
63
63
  end
64
64
 
65
- require_libraries
65
+ if @libraries
66
+ vputs "[pl:#{@name}] Requiring libs..."
67
+ require_libraries
68
+ vputs "[pl:#{@name}] Done requiring libs."
69
+ end
66
70
 
67
71
  return unless @on_load
72
+ fail PluginLoadFailure, name unless @on_load.kind_of?(Proc)
68
73
 
69
- if @on_load.kind_of?(Proc)
70
- @on_load.call
71
- else
72
- fail PluginLoadFailure, name
73
- end
74
+ @on_load.call
74
75
  end
75
76
  end
76
77
  end
@@ -1,7 +1,7 @@
1
1
  require 'hairballs'
2
2
 
3
3
  Hairballs.add_plugin(:awesome_print) do |plugin|
4
- plugin.libraries %w(awesome_print)
4
+ plugin.libraries %w[awesome_print]
5
5
 
6
6
  plugin.on_load do
7
7
  AwesomePrint.irb!
@@ -8,7 +8,7 @@ require 'hairballs'
8
8
  #
9
9
  # TODO: fix to work with using/loading before Wirble.
10
10
  Hairballs.add_plugin(:colorize_json, color: :blue) do |plugin|
11
- plugin.libraries %w(json colorize)
11
+ plugin.libraries %w[json colorize]
12
12
 
13
13
  plugin.on_load do
14
14
  IRB::Irb.class_eval do
@@ -3,7 +3,7 @@ require 'hairballs'
3
3
  Hairballs.add_plugin(:irb_history, save_history: 1000,
4
4
  eval_history: 20,
5
5
  global_history_file: true) do |plugin|
6
- plugin.libraries %w(irb/ext/save-history)
6
+ plugin.libraries %w[irb/ext/save-history]
7
7
 
8
8
  plugin.on_load do
9
9
  IRB.conf[:SAVE_HISTORY] = plugin.save_history
@@ -3,13 +3,13 @@ require 'hairballs'
3
3
  # Directly lifted from rbates/dotfiles! Adds +#ri+ to all Objects, letting you
4
4
  # get ri docs from within your IRB session.
5
5
  Hairballs.add_plugin(:object_ri) do |plugin|
6
- plugin.libraries %w(rdoc)
6
+ plugin.libraries %w[rdoc]
7
7
 
8
8
  plugin.on_load do
9
9
  Object.class_eval do
10
10
  def ri(method=nil)
11
11
  unless method && method =~ /^[A-Z]/ # if class isn't specified
12
- klass = self.kind_of?(Class) ? name : self.class.name
12
+ klass = kind_of?(Class) ? name : self.class.name
13
13
  method = [klass, method].compact.join('#')
14
14
  end
15
15
 
@@ -4,11 +4,11 @@ require 'hairballs'
4
4
  #
5
5
  # @see http://stackoverflow.com/a/123834/172106
6
6
  Hairballs.add_plugin(:quick_benchmark) do |plugin|
7
- plugin.libraries %w(benchmark)
7
+ plugin.libraries %w[benchmark]
8
8
 
9
9
  plugin.on_load do
10
10
  Kernel.module_eval do
11
- def quick_benchmark(repetitions=100, &block)
11
+ def quick_benchmark(repetitions=20, &block)
12
12
  Benchmark.bmbm do |b|
13
13
  b.report { repetitions.times(&block) }
14
14
  end
@@ -2,7 +2,7 @@ require 'hairballs'
2
2
 
3
3
  # Just loads Wirble.
4
4
  Hairballs.add_plugin(:wirble) do |plugin|
5
- plugin.libraries %w(wirble)
5
+ plugin.libraries %w[wirble]
6
6
 
7
7
  plugin.on_load do
8
8
  Wirble.init
@@ -4,61 +4,81 @@ class Hairballs
4
4
  #
5
5
  # TODO: Make it nicer to define Pry prompts.
6
6
  class Prompt
7
- # @param [Boolean]
8
- attr_accessor :auto_indent
9
-
10
- # The normal prompt string. Same as
11
- # IRB.conf[:PROMPT][ prompt name ][:PROMPT_I]
7
+ # @!attribute irb_prompt_options [r]
8
+ # After setting values using the Prompt's setter methods, this Hash will
9
+ # represent those values using keys that correlate to
10
+ # IRB.conf[:PROMPT][:MY_PROMPT].
12
11
  #
13
- # @param [String]
14
- attr_accessor :normal
15
- alias_method :i, :normal
16
- alias_method :i=, :normal=
12
+ # @return [Hash]
13
+ attr_reader :irb_prompt_options
17
14
 
18
- # The prompt for when strings wrap multiple lines. Same as
19
- # IRB.conf[:PROMPT][ prompt name ][:PROMPT_S]
15
+ def initialize
16
+ vputs 'Setting up prompt...'
17
+ @irb_prompt_options = IRB.conf[:PROMPT][:NULL].dup
18
+ end
19
+
20
+ # Wrapper for setting IRB.conf[:PROMPT][:MY_PROMPT][:PROMPT_C].
21
+ # The prompt for when statements wrap multiple lines.
20
22
  #
21
- # @param [String]
22
- attr_accessor :continued_string
23
- alias_method :s, :continued_string
24
- alias_method :s=, :continued_string=
23
+ # @param new_continued_statement [String]
24
+ def continued_statement=(new_continued_statement)
25
+ @irb_prompt_options[:PROMPT_C] = new_continued_statement
26
+ end
25
27
 
26
- # The prompt for when statements wrap multiple lines. Same as
27
- # IRB.conf[:PROMPT][ prompt name ][:PROMPT_C]
28
+ # @return [String]
29
+ def continued_statement
30
+ @irb_prompt_options[:PROMPT_C]
31
+ end
32
+
33
+ # Wrapper for setting IRB.conf[:PROMPT][:MY_PROMPT][:PROMPT_S].
34
+ # The prompt for when strings wrap multiple lines.
28
35
  #
29
- # @param [String]
30
- attr_accessor :continued_statement
31
- alias_method :c, :continued_statement
32
- alias_method :c=, :continued_statement=
36
+ # @param new_continued_string [String]
37
+ def continued_string=(new_continued_string)
38
+ @irb_prompt_options[:PROMPT_S] = new_continued_string
39
+ end
40
+
41
+ # @return [String]
42
+ def continued_string
43
+ @irb_prompt_options[:PROMPT_S]
44
+ end
33
45
 
34
- # The prompt for when statements include indentation. Same as
35
- # IRB.conf[:PROMPT][ prompt name ][:PROMPT_N]
46
+ # Wrapper for setting IRB.conf[:PROMPT][:MY_PROMPT][:PROMPT_N].
47
+ # The prompt for when statements include indentation.
36
48
  #
37
- # @param [String]
38
- attr_accessor :indented_code
39
- alias_method :n, :indented_code
40
- alias_method :n=, :indented_code=
49
+ # @param new_indented_code [String]
50
+ def indented_code=(new_indented_code)
51
+ @irb_prompt_options[:PROMPT_N] = new_indented_code
52
+ end
41
53
 
42
- # The prompt for return values. Same as
43
- # IRB.conf[:PROMPT][ prompt name ][:RETURN]
54
+ # @return [String]
55
+ def indented_code
56
+ @irb_prompt_options[:PROMPT_N]
57
+ end
58
+
59
+ # Wrapper for setting IRB.conf[:PROMPT][:MY_PROMPT][:PROMPT_I].
44
60
  #
45
- # @param [String]
46
- attr_accessor :return_format
61
+ # @param new_normal [String]
62
+ def normal=(new_normal)
63
+ @irb_prompt_options[:PROMPT_I] = new_normal
64
+ end
47
65
 
48
- # @return [Hash] A set of key/value pairs that can be used to pass to a
49
- # IRB.conf[:PROMPT][ prompt name ].
50
- def irb_configuration
51
- vputs 'Setting up prompt...'
66
+ # @return [String]
67
+ def normal
68
+ @irb_prompt_options[:PROMPT_I]
69
+ end
52
70
 
53
- prompt_values = {}
54
- prompt_values[:AUTO_INDENT] = @auto_indent if @auto_indent
55
- prompt_values[:PROMPT_C] = continued_statement unless continued_statement.empty?
56
- prompt_values[:PROMPT_I] = normal unless normal.empty?
57
- prompt_values[:PROMPT_N] = indented_code unless indented_code.empty?
58
- prompt_values[:PROMPT_S] = continued_string unless continued_string.empty?
59
- prompt_values[:RETURN] = @return_format if @return_format
71
+ # Wrapper for setting IRB.conf[:PROMPT][:MY_PROMPT][:RETURN]. The prompt
72
+ # for how to display return values.
73
+ #
74
+ # @param new_return_format [String]
75
+ def return_format=(new_return_format)
76
+ @irb_prompt_options[:RETURN] = new_return_format
77
+ end
60
78
 
61
- prompt_values
79
+ # @return [String]
80
+ def return_format
81
+ @irb_prompt_options[:RETURN]
62
82
  end
63
83
  end
64
84
  end
@@ -12,18 +12,20 @@ class Hairballs
12
12
  class Theme
13
13
  include Hairballs::LibraryHelpers
14
14
 
15
- # Just an identifier for the Theme. Don't name two themes the same
16
- # name--that will cause problems.
15
+ # @!attribute name [rw]
16
+ # Just an identifier for the Theme. Don't name two themes the same
17
+ # name--that will cause problems.
17
18
  #
18
- # @param [Symbol]
19
+ # @return [Symbol]
19
20
  attr_accessor :name
20
21
 
21
- # Tells Hairballs to do some hackery to let Themes use gems that aren't
22
- # specified in your app's Gemfile. This alleviates you from having to
23
- # declare gems in your Gemfile simply for the sake of managing your personal
24
- # IRB preferences.
22
+ # @!attribute extend_bundler [rw]
23
+ # Tells Hairballs to do some hackery to let Themes use gems that aren't
24
+ # specified in your app's Gemfile. This alleviates you from having to
25
+ # declare gems in your Gemfile simply for the sake of managing your
26
+ # personal IRB preferences.
25
27
  #
26
- # @param [Boolean]
28
+ # @return [Boolean]
27
29
  attr_accessor :extend_bundler
28
30
 
29
31
  # @param name [Symbol]
@@ -36,8 +38,10 @@ class Hairballs
36
38
  # Tell IRB to use this Theme.
37
39
  def use!
38
40
  do_bundler_extending if @extend_bundler
41
+ vputs "[th:#{@name}] Requiring libs..."
39
42
  require_libraries
40
43
  set_up_prompt
44
+ vputs "[th:#{@name}] Done setting up."
41
45
  end
42
46
 
43
47
  # The name of the Theme, but in the format that IRB.conf[:PROMPT] likes (an
@@ -79,7 +83,8 @@ class Hairballs
79
83
  end
80
84
 
81
85
  def set_up_irb_prompt
82
- IRB.conf[:PROMPT][irb_name] = @prompt.irb_configuration
86
+ vputs "[th:#{@name}] Prompt options: #{@prompt.irb_prompt_options}"
87
+ IRB.conf[:PROMPT][irb_name] = @prompt.irb_prompt_options
83
88
  IRB.conf[:PROMPT_MODE] = irb_name
84
89
  IRB.CurrentContext.prompt_mode = irb_name if IRB.CurrentContext
85
90
  end
@@ -92,7 +97,9 @@ class Hairballs
92
97
  elsif @prompt.normal
93
98
  ::Pry.config.prompt = -> { @prompt.normal }
94
99
  else
95
- vputs 'Neither "normal" nor "continued_statement" prompts configured.'
100
+ # rubocop:disable Metrics/LineLength
101
+ vputs %([th:#{@name}] Neither "normal" nor "continued_statement" prompts configured.)
102
+ # rubocop:enable
96
103
  end
97
104
  end
98
105
 
@@ -102,7 +109,7 @@ class Hairballs
102
109
  output.printf @prompt.return_format, value.inspect
103
110
  end
104
111
  else
105
- vputs '"return_format" not configured.'
112
+ vputs %([th:#{@name}] "return_format" not configured.)
106
113
  end
107
114
  end
108
115
  end
@@ -1,28 +1,30 @@
1
1
  require 'hairballs'
2
2
 
3
3
  Hairballs.add_theme(:turboladen) do |theme|
4
+ IRB.conf[:AUTO_INDENT] = true
5
+
4
6
  theme.libraries do |libs_to_require|
5
- libs_to_require += %w(
7
+ libs_to_require += %w[
8
+ awesome_print
6
9
  irb/completion
7
10
  looksee
8
11
  colorize
9
- )
12
+ ]
10
13
 
11
14
  libs_to_require +=
12
15
  case RUBY_PLATFORM
13
- when /mswin32|mingw32/
14
- %w(win32console)
15
- when /darwin/
16
- %w(terminal-notifier)
17
- else
18
- []
16
+ when /mswin32|mingw32/ then %w[win32console]
17
+ when /darwin/ then %w[terminal-notifier]
18
+ else []
19
19
  end
20
20
 
21
21
  libs_to_require
22
22
  end
23
23
 
24
24
  theme.prompt do |prompt|
25
- preface = proc do |status = ' '|
25
+ status = ' '.freeze
26
+
27
+ preface = proc do
26
28
  if Hairballs.project_name
27
29
  "⟪#{Hairballs.project_name.light_blue}⟫#{status}%03n"
28
30
  else
@@ -30,11 +32,10 @@ Hairballs.add_theme(:turboladen) do |theme|
30
32
  end
31
33
  end
32
34
 
33
- prompt.auto_indent = true
34
35
  prompt.normal = "#{preface.call}:%i> "
35
36
  prompt.continued_string = "#{preface.call('❊%l'.yellow)}:%i> "
36
37
  prompt.continued_statement = "#{preface.call('❊?'.yellow)}:%i> "
37
38
  prompt.indented_code = "#{preface.call('✚ '.yellow)}:%i> "
38
- prompt.return_format = "➥ %s\n"
39
+ prompt.return_format = "➥ %s\n".freeze
39
40
  end
40
41
  end
@@ -2,20 +2,18 @@ require 'hairballs'
2
2
 
3
3
  Hairballs.add_theme(:turboladen_rails) do |theme|
4
4
  theme.libraries do |libs_to_require|
5
- libs_to_require += %w(
5
+ libs_to_require += %w[
6
+ awesome_print
6
7
  irb/completion
7
8
  looksee
8
9
  colorize
9
- )
10
+ ]
10
11
 
11
12
  libs_to_require +=
12
13
  case RUBY_PLATFORM
13
- when /mswin32|mingw32/
14
- %w(win32console)
15
- when /darwin/
16
- %w(terminal-notifier)
17
- else
18
- []
14
+ when /mswin32|mingw32/ then %w[win32console]
15
+ when /darwin/ then %w[terminal-notifier]
16
+ else []
19
17
  end
20
18
 
21
19
  libs_to_require
@@ -24,12 +22,11 @@ Hairballs.add_theme(:turboladen_rails) do |theme|
24
22
  theme.extend_bundler = true
25
23
 
26
24
  theme.prompt do |prompt|
27
- prompt.auto_indent = true
28
- preface = Hairballs.project_name.light_blue
29
- prompt.normal = "#{preface}> "
25
+ preface = Hairballs.project_name.light_blue.freeze
26
+ prompt.normal = "#{preface}> ".freeze
30
27
  prompt.continued_string = "#{preface}#{'❊%l'.yellow}> "
31
28
  prompt.continued_statement = "#{preface}#{'⇥'.yellow} %i> "
32
29
  prompt.indented_code = "#{preface}#{'⇥'.yellow} %i> "
33
- prompt.return_format = "➥ %s\n"
30
+ prompt.return_format = "➥ %s\n".freeze
34
31
  end
35
32
  end
@@ -1,4 +1,4 @@
1
1
  class Hairballs
2
2
  # @return [String]
3
- VERSION = '0.1.3'
3
+ VERSION = '0.2.0'.freeze
4
4
  end
@@ -95,34 +95,22 @@ RSpec.describe Hairballs::Configuration do
95
95
  describe '#add_plugin' do
96
96
  let(:plugin) { double 'Hairballs::Plugin' }
97
97
 
98
- context 'block given and name param is a Symbol' do
99
- before do
100
- expect(Hairballs::Plugin).to receive(:new).with(:test, {}).
101
- and_return plugin
102
- end
103
-
104
- it 'yields the Plugin' do
105
- expect { |b| subject.add_plugin(:test, &b) }.to yield_with_args(plugin)
106
- end
107
-
108
- it 'adds the Plugin to @plugins' do
109
- expect(subject.plugins).to receive(:<<).with(plugin)
110
- subject.add_plugin(:test) { |_| }
111
- end
98
+ before do
99
+ expect(Hairballs::Plugin).to receive(:new).with(:test, {}).
100
+ and_return plugin
101
+ end
112
102
 
113
- it 'returns the Plugin' do
114
- expect(subject.add_plugin(:test) { |_| }).to eq plugin
115
- end
103
+ it 'yields the Plugin' do
104
+ expect { |b| subject.add_plugin(:test, &b) }.to yield_with_args(plugin)
116
105
  end
117
106
 
118
- context 'no block given' do
119
- before do
120
- allow(Hairballs::Plugin).to receive(:new).and_return plugin
121
- end
107
+ it 'adds the Plugin to @plugins' do
108
+ expect(subject.plugins).to receive(:<<).with(plugin)
109
+ subject.add_plugin(:test) { |_| }
110
+ end
122
111
 
123
- it 'raises a LocalJumpError' do
124
- expect { subject.add_plugin(:test) }.to raise_exception(LocalJumpError)
125
- end
112
+ it 'returns the Plugin' do
113
+ expect(subject.add_plugin(:test) { |_| }).to eq plugin
126
114
  end
127
115
  end
128
116
 
@@ -49,6 +49,8 @@ RSpec.describe Hairballs::LibraryHelpers do
49
49
 
50
50
  context '@libraries is not nil' do
51
51
  let(:lib_name) { 'asdfqwer' }
52
+ let(:dependency_requirer) { instance_double 'Fiber' }
53
+ let(:dependency_installer) { instance_double 'Fiber' }
52
54
 
53
55
  before do
54
56
  subject.instance_variable_set(:@libraries, [lib_name])
@@ -57,10 +59,12 @@ RSpec.describe Hairballs::LibraryHelpers do
57
59
 
58
60
  context 'libraries are not installed' do
59
61
  it 'tries two times to require then Gem.install' do
60
- expect(subject).to receive(:start_install_thread).
61
- with(lib_name, instance_of(Queue))
62
- expect(subject).to receive(:start_require_thread).
63
- with(instance_of(Queue))
62
+ expect(subject).to receive(:new_dependency_requirer).
63
+ with(instance_of(Fiber)).and_return(dependency_requirer)
64
+ expect(subject).to receive(:install_missing_dependencies).
65
+ with([lib_name], dependency_requirer).
66
+ and_return(dependency_installer)
67
+ expect(dependency_installer).to receive(:resume)
64
68
 
65
69
  subject.require_libraries
66
70
  end
@@ -74,63 +78,23 @@ RSpec.describe Hairballs::LibraryHelpers do
74
78
  end
75
79
  end
76
80
 
77
- describe '#start_install_thread' do
78
- before { allow(Thread).to receive(:new).and_yield }
79
- let(:require_queue) { instance_double 'Queue' }
80
- let(:lib_name) { 'some lib' }
81
+ describe '#install_missing_dependencies' do
82
+ let(:source) { instance_double 'Fiber' }
83
+ before { expect(Fiber).to receive(:new).and_yield }
81
84
 
82
- context 'gem exists' do
83
- let(:gem) { double 'Gem::Specification' }
85
+ context 'deps are empty' do
86
+ it 'never resumes the source fiber' do
87
+ expect(source).to_not receive(:resume)
84
88
 
85
- it 'puts the library name on the require_queue' do
86
- expect(Gem).to receive(:install).with(lib_name).and_return([gem])
87
- expect(require_queue).to receive(:<<).with(lib_name)
88
-
89
- subject.send(:start_install_thread, lib_name, require_queue)
89
+ subject.send(:install_missing_dependencies, [], source)
90
90
  end
91
91
  end
92
92
 
93
- context 'gem does not exist' do
94
- it 'does not put the library name on the require_queue' do
95
- expect(Gem).to receive(:install).with(lib_name).and_return([])
96
- expect(require_queue).to_not receive(:<<)
97
-
98
- subject.send(:start_install_thread, lib_name, require_queue)
99
- end
100
- end
101
- end
102
-
103
- describe '#start_require_thread' do
104
- let(:require_queue) { instance_double 'Queue' }
105
- let(:lib_name) { 'test name' }
106
- let(:thread) { instance_double('Thread', join: nil) }
107
- before { allow(Thread).to receive(:new).and_yield.and_return(thread) }
108
-
109
- context 'rails' do
110
- before { expect(Hairballs.config).to receive(:rails?).and_return(true) }
111
-
112
- it 'finds the latest gem and adds it to the load path' do
113
- lib_path = 'path to lib'
114
- expect(require_queue).to receive(:pop).and_return(lib_name)
115
- expect(subject).to receive(:find_latest_gem).with(lib_name).
116
- and_return(lib_path)
117
- expect($LOAD_PATH).to receive(:unshift).with('path to lib/lib')
118
- expect(subject).to receive(:require).with(lib_name)
119
-
120
- subject.send(:start_require_thread, require_queue)
121
- end
122
- end
123
-
124
- context 'not rails' do
125
- before { expect(Hairballs.config).to receive(:rails?).and_return(false) }
126
-
127
- it 'does not find the latest gem and add it to the load path' do
128
- expect(require_queue).to receive(:pop).and_return(lib_name)
129
- expect(subject).to_not receive(:find_latest_gem)
130
- expect($LOAD_PATH).to_not receive(:unshift)
131
- expect(subject).to receive(:require).with(lib_name)
93
+ context 'deps are not empty' do
94
+ it 'resumes the source fiber with the name of the dep' do
95
+ expect(source).to receive(:resume).with('meow')
132
96
 
133
- subject.send(:start_require_thread, require_queue)
97
+ subject.send(:install_missing_dependencies, ['meow'], source)
134
98
  end
135
99
  end
136
100
  end
@@ -2,7 +2,9 @@ require 'spec_helper'
2
2
  require 'hairballs/theme'
3
3
 
4
4
  RSpec.describe Hairballs::Theme do
5
+ let(:prompt) { instance_double 'Hairballs::Prompt' }
5
6
  subject(:theme) { described_class.new(:test) }
7
+ before { allow(Hairballs::Prompt).to receive(:new).and_return(prompt) }
6
8
 
7
9
  describe '#irb_name' do
8
10
  subject { theme.irb_name }
metadata CHANGED
@@ -1,55 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hairballs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.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: 2015-07-13 00:00:00.000000000 Z
11
+ date: 2016-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.7'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.7'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3.1'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.1'
55
55
  description: Like oh-my-zsh, but for IRB.
@@ -59,10 +59,10 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
- - ".gitignore"
63
- - ".rspec"
64
- - ".rubocop.yml"
65
- - ".travis.yml"
62
+ - .gitignore
63
+ - .rspec
64
+ - .rubocop.yml
65
+ - .travis.yml
66
66
  - Gemfile
67
67
  - History.md
68
68
  - LICENSE.txt
@@ -105,17 +105,17 @@ require_paths:
105
105
  - lib
106
106
  required_ruby_version: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - ">="
108
+ - - '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  required_rubygems_version: !ruby/object:Gem::Requirement
112
112
  requirements:
113
- - - ">="
113
+ - - '>='
114
114
  - !ruby/object:Gem::Version
115
115
  version: '0'
116
116
  requirements: []
117
117
  rubyforge_project:
118
- rubygems_version: 2.4.6
118
+ rubygems_version: 2.5.1
119
119
  signing_key:
120
120
  specification_version: 4
121
121
  summary: Like oh-my-zsh, but for IRB.