hairballs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4d0f86e9c3d02f22b832c4b3edce907001d0db2f
4
+ data.tar.gz: 7ddc281fd14c1d9c673b59bd6ca1f218e1722f2a
5
+ SHA512:
6
+ metadata.gz: 0ed4bf7812d457c37d006c4b6b065a6a05df37aba2991f77fa261aa2939bc51ef1df35a55d861a75b5fc93ffe556d4a102a618f99f84dc4126a174679fa4311b
7
+ data.tar.gz: 11bf1690a4fd0c528223c4608bbc757a17720f64dfdc137ffe58abae6e505499c790e32c711203f2d768fabfe09900b6c0f6b9872dbb5da9539e50164f211c53
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hairballs.gemspec
4
+ gemspec
data/History.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.0.1 / 2014-12-19
2
+
3
+ * Happy Birthday!
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Steve Loveless
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,250 @@
1
+ hairballs
2
+ =========
3
+
4
+ Aka, "haIRBalls". Like [oh-my-zsh](http://ohmyz.sh), but for IRB.
5
+
6
+ wat
7
+ ---
8
+
9
+ haIRBalls is a framework for managing your IRB configuration.
10
+
11
+ Installation
12
+ ------------
13
+
14
+ For non-Bundlered apps, install it yourself as:
15
+
16
+ $ gem install hairballs
17
+
18
+ For Bundlered apps, you have a couple options:
19
+
20
+ 1. Add `gem 'hairballs'` to your Gemfile.
21
+ 1. Manually add `hairballs` to the load path:
22
+
23
+ ```ruby
24
+ hairballs_path = Dir.glob("#{Gem.dir}/gems/hairballs-*/lib")
25
+ $LOAD_PATH.unshift(hairballs_path.first) unless hairballs_path.empty?
26
+ require 'hairballs'
27
+ ```
28
+
29
+ Usage
30
+ -----
31
+
32
+ Hairballs provides you with methods and such for creating "themes" and "plugins"
33
+ that you add in to your IRB sessions.
34
+
35
+ ### Themes ###
36
+
37
+ Initially *themes* are for defining an IRB prompt using a cleaner API than the
38
+ one provide by IRB. They are a) reusable and b) can be switched on the fly,
39
+ without requiring a reload of IRB. Hairballs also provides methods for dealing
40
+ with dependencies and getting those dependencies to play nice with Bundler.
41
+
42
+ **Example: A Rails Theme**
43
+
44
+ This:
45
+
46
+ ```ruby
47
+ # ~/.irbrc
48
+
49
+ # Specify dependencies.
50
+ libraries = %w[irb/completion awesome_print wirble looksee]
51
+
52
+ libraries += case RUBY_PLATFORM
53
+ when /mswin32|mingw32/
54
+ %w[win32console]
55
+ when /darwin/
56
+ %w[terminal-notifier]
57
+ else
58
+ []
59
+
60
+ # Only setup prompt if Rails.
61
+ if ENV['RAILS_ENV'] || defined? Rails
62
+ # Allow non-Gemfile deps to work with Rails.
63
+ if defined?(::Bundler)
64
+ all_global_gem_paths = Dir.glob("#{Gem.dir}/gems/*")
65
+
66
+ all_global_gem_paths.each do |p|
67
+ gem_path = "#{p}/lib"
68
+ $:.unshift(gem_path)
69
+ end
70
+ end
71
+
72
+ # Setup the prompt.
73
+ rails_root = File.basename(Dir.pwd)
74
+
75
+ IRB.conf[:PROMPT][:RAILS] = {
76
+ AUTO_INDENT: true,
77
+ PROMPT_I: "#{rails_root}> ",
78
+ PROMPT_S: "#{rails_root}❊%l> ",
79
+ PROMPT_C: "#{rails_root}⇥ %i> ",
80
+ PROMPT_N: "#{rails_root}⇥ %i> ",
81
+ RETURN: "➥ %s\n"
82
+ }
83
+ IRB.conf[:PROMPT_MODE] = :RAILS
84
+ end
85
+
86
+ # Require/install dependencies.
87
+ libraries.each do |lib|
88
+ retry_count = 0
89
+
90
+ begin
91
+ break if retry_count == 2
92
+ puts "Requiring library: #{lib}"
93
+ require lib
94
+ rescue LoadError
95
+ puts "#{lib} not installed; installing now..."
96
+ Gem.install lib
97
+ retry_count += 1
98
+ retry
99
+ end
100
+ end
101
+ ```
102
+
103
+ ...becomes this:
104
+
105
+ ```ruby
106
+ # hairballs/themes/turboladen_rails.rb
107
+ Hairballs.add_theme(:turboladen_rails) do |theme|
108
+ theme.libraries do
109
+ libs_to_require = %w(irb/completion looksee wirble awesome_print)
110
+
111
+ libs_to_require +
112
+ case RUBY_PLATFORM
113
+ when /mswin32|mingw32/
114
+ %w(win32console)
115
+ when /darwin/
116
+ %w(terminal-notifier)
117
+ else
118
+ []
119
+ end
120
+ end
121
+
122
+ theme.extend_bundler = true
123
+
124
+ theme.prompt do |prompt|
125
+ preface = Hairballs.project_name
126
+
127
+ prompt.auto_indent = true
128
+ prompt.normal = "#{preface}> "
129
+ prompt.continued_string = "#{preface}❊%l> "
130
+ prompt.continued_statement = "#{preface}⇥ %i> "
131
+ prompt.indented_code = "#{preface}⇥ %i> "
132
+ prompt.return_format = "➥ %s\n"
133
+ end
134
+ end
135
+
136
+ # ~/.irbrc
137
+ require 'hairballs/themes/turboladen_rails'
138
+
139
+ if Hairballs.rails?
140
+ Hairballs.use_theme(:turboladen_rails)
141
+ end
142
+ ```
143
+
144
+ In the end, your .irbrc is cleaned up and the theme used there can be reused and
145
+ maintained separately. Check out the `Hairballs::Theme` docs and existing
146
+ themes under lib/hairballs/themes/ for more details and ideas.
147
+
148
+ ### Plugins ###
149
+
150
+ *Plugins* are similar to *themes* in that they let you abstract away some code
151
+ from your .irbrc, thus making it cleaner and more maintainable. The essence of
152
+ plugins, however, is to allow you to change the behavior of or add behavior to
153
+ IRB; this could mean things like:
154
+
155
+ * Installing and configuring dependencies for IRB use.
156
+ * Adding helper methods to your IRB session.
157
+ * Adding methods to certain objects, say, for debugging.
158
+ * Changing how certain objects are displayed when returned from methods.
159
+
160
+ **Example: Wirble**
161
+
162
+ Wirble has been around for years and I still like it for colorizing returned
163
+ objects in IRB. Using a Hairballs plugin for wrapping this a) ensures wirble
164
+ is installed any time I want to use it, and b) runs the initializing of wirble
165
+ but keeps the code for doing so outside of my .irbrc.
166
+
167
+ ```ruby
168
+ # hairballs/plugins/wirble.rb
169
+ Hairballs.add_plugin(:wirble) do |plugin|
170
+ plugin.libraries %w(wirble)
171
+
172
+ plugin.on_load do
173
+ Wirble.init
174
+ Wirble.colorize
175
+ end
176
+ end
177
+
178
+ # ~/.irbrc
179
+ require 'hairballs/plugins/wirble'
180
+
181
+ Hairballs.load_plugin(:wirble)
182
+ ```
183
+
184
+ Check out the Hairballs::Plugin docs and existing plugins under
185
+ lib/hairballs/plugins/ for more details and ideas.
186
+
187
+ I've got my `.irbrc` (using Hairballs) stored on the interwebs
188
+ [here](https://github.com/turboladen/config_files/blob/master/.irbrc) if
189
+ that's of any help or interest.
190
+
191
+ But whyyyy?
192
+ --------
193
+
194
+ There's some similar tools out there, but they seemed overly complicated. IRB
195
+ is a tool for doing development and those, in my opinion, should be as simple
196
+ and straightforward as possible.
197
+
198
+ **tl:dr**
199
+
200
+ I wanted to...
201
+
202
+ * abstract away some of IRB's weirdness.
203
+ * manage IRB dependencies based on my preferences.
204
+ * for Bundler apps, use gems in IRB without having to add them to your Gemfile.
205
+ * keep `.irbrc` clean. Make helpers reusable.
206
+
207
+ **Moar explain.**
208
+
209
+ Some problems I faced:
210
+
211
+ * Rails console loads ~/.irbrc. If you have gem dependencies in there, you
212
+ have to add them to your Gemfile to add them to the bundle.
213
+ * This doesn't make sense to me. You shouldn't make the others that are
214
+ developing that app with you use gems for *your* IRB configuration.
215
+ * *Solution:* `Hairballs::LibraryHelpers#libraries` and
216
+ `Hairballs::LibraryHelpers#require_libraries`, which are available to *Themes*
217
+ and *Plugins*.
218
+ * I want different prompt styles for regular ol' IRB vs Rails console.
219
+ * *Solution:* `Hairballs::Theme`s.
220
+ * Customizing my prompt(s) felt so clunky!
221
+ * *Solution:* `Hairballs::Theme`s.
222
+ * Installing and using new Rubies then running IRB meant I had to exit out and
223
+ manually install them all.
224
+ * zzzzzzzz...
225
+ * *Solution:* `Hairballs::LibraryHelpers#libraries` and
226
+ `Hairballs::LibraryHelpers#require_libraries`.
227
+ * I kept having problems with IRB and history getting all out of order--usually
228
+ with Rails. I was using `'irb/history'`, but trying to figure out what was
229
+ wrong was difficult since my .irbrc had become a sprawling mass of one-off
230
+ methods and blocks.
231
+ * *Solution:* `hairballs/plugins/irb_history`. This sets up IRB to use its
232
+ `*HISTORY*` settings properly and cleanly.
233
+ * Specifying gems as IRB dependencies for different Ruby interpreters is simple
234
+ but can clutter up your .irbrc.
235
+ * Putting the deps with the plugin or theme that needs them keeps everything
236
+ together and out of the .irbrc.
237
+ * *Solution:* *Themes* and *Plugins* let you specify only the gems you need
238
+ for those items. Logic surrounding that (ex. platform-specific) is kept
239
+ out of your .irbrc.
240
+
241
+ Contributing
242
+ ------------
243
+
244
+ Your themes and plugins are welcome!
245
+
246
+ 1. Fork it ( https://github.com/turboladen/hairballs/fork )
247
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
248
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
249
+ 4. Push to the branch (`git push origin my-new-feature`)
250
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
data/hairballs.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hairballs/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'hairballs'
8
+ spec.version = Hairballs::VERSION
9
+ spec.authors = ['Steve Loveless']
10
+ spec.email = ['steve.loveless@gmail.com']
11
+ spec.summary = 'Like oh-my-zsh, but for IRB.'
12
+ spec.description = 'Some tools for making customizing your IRB sessions a little easier.'
13
+ spec.homepage = 'https://github.com/turboladen/hairballs'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(spec)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.7'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+ spec.add_development_dependency 'rspec', '~> 3.1'
24
+ end
@@ -0,0 +1,22 @@
1
+ class Hairballs
2
+ class PluginNotFound < RuntimeError
3
+ def initialize(plugin_name)
4
+ message = "Plugin not found: :#{plugin_name}."
5
+ super(message)
6
+ end
7
+ end
8
+
9
+ class PluginLoadFailure < RuntimeError
10
+ def initialize(plugin_name)
11
+ message = "Unable to load plugin: :#{plugin_name}."
12
+ super(message)
13
+ end
14
+ end
15
+
16
+ class ThemeUseFailure < RuntimeError
17
+ def initialize(theme_name)
18
+ message = "Theme not found: :#{theme_name}."
19
+ super(message)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,7 @@
1
+ module Kernel
2
+ # Does a puts only if IRB is in verbose mode.
3
+ def vputs(*messages)
4
+ messages.map! { |m| "[Hairballs] #{m}" }
5
+ puts(*messages) if defined?(::IRB) && ::IRB.conf[:VERBOSE]
6
+ end
7
+ end
@@ -0,0 +1,85 @@
1
+ class Hairballs
2
+ # Helpers specifying and requiring dependencies for Themes and Plugins.
3
+ module LibraryHelpers
4
+ # @param libs [Array<String>]
5
+ def libraries(libs=nil)
6
+ return @libraries if @libraries && libs.nil?
7
+
8
+ @libraries = block_given? ? yield : libs
9
+
10
+ unless @libraries.is_a?(Array)
11
+ fail ArgumentError,
12
+ "Block must return an Array but returned #{@libraries}."
13
+ end
14
+
15
+ @libraries
16
+ end
17
+
18
+ # Requires #libraries on load. If they're not installed, install them. If
19
+ # it can't be installed, move on to the next.
20
+ def require_libraries
21
+ return if @libraries.nil?
22
+
23
+ @libraries.each do |lib|
24
+ retry_count = 0
25
+
26
+ begin
27
+ next if retry_count == 2
28
+ vputs "Requiring library: #{lib}"
29
+ require lib
30
+ rescue LoadError
31
+ puts "#{lib} not installed; installing now..."
32
+ Gem.install lib
33
+
34
+ if Hairballs.rails?
35
+ installed_gem = find_latest_gem(lib)
36
+ $LOAD_PATH.unshift("#{installed_gem}/lib")
37
+ end
38
+
39
+ require lib
40
+ retry_count += 1
41
+ retry
42
+ end
43
+ end
44
+ end
45
+
46
+ def find_latest_gem(gem_name)
47
+ the_gem = Dir.glob("#{Gem.dir}/gems/#{gem_name}-*")
48
+
49
+ the_gem.empty? ? nil : the_gem.first
50
+ end
51
+
52
+ # Add all gems in the global gemset to the $LOAD_PATH so they can be used
53
+ # even in places like 'rails console'.
54
+ #
55
+ # TODO: Use #find_latest_gem for each of #libraries.
56
+ def do_bundler_extending
57
+ if defined?(::Bundler)
58
+ all_global_gem_paths = Dir.glob("#{Gem.dir}/gems/*")
59
+
60
+ all_global_gem_paths.each do |p|
61
+ gem_path = "#{p}/lib"
62
+ $LOAD_PATH.unshift(gem_path)
63
+ end
64
+ else
65
+ vputs 'Bundler not defined. Skipping.'
66
+ end
67
+ end
68
+
69
+ # Undo the stuff that was done in #do_bundler_extending.
70
+ #
71
+ # TODO: Use #find_latest_gem for each of #libraries.
72
+ def undo_bundler_extending
73
+ if defined?(::Bundler)
74
+ all_global_gem_paths = Dir.glob("#{Gem.dir}/gems/*")
75
+
76
+ all_global_gem_paths.each do |p|
77
+ gem_path = "#{p}/lib"
78
+ $LOAD_PATH.delete(gem_path)
79
+ end
80
+ else
81
+ vputs 'Bundler not defined. Skipping.'
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,75 @@
1
+ require_relative 'library_helpers'
2
+
3
+ class Hairballs
4
+ # Plugins provide means for adding functionality to your IRB sessions. They
5
+ # can be as simple as requiring other gems, or as complex as you want them to
6
+ # be.
7
+ #
8
+ # One benefit of making a simple plugin for requiring other deps is
9
+ # Hairballs::LibraryHelpers#require_libraries method. When used in conjunction with
10
+ # Hairballs::LibraryHelpers#libraries, you don't have to worry about installing the
11
+ # gems before using IRB. This is particularly helpful when using a Ruby
12
+ # manager (RVM, rbenv, etc) and you install a new Ruby; if you don't think
13
+ # ahead to install your IRB deps, your IRB session won't behave like you
14
+ # want; well, not until you `exit` and fix the problem. This simple pattern
15
+ # helps alleviate that small headache.
16
+ #
17
+ # Next, Hairballs Plugins are lazily loaded; `require`ing their source files
18
+ # doesn't mean the methods and such that you add there will do anything; it's
19
+ # not until you `Hairballs.load_plugin(:blargh)` that the code that defines
20
+ # your plugin will get executed.
21
+ class Plugin
22
+ include LibraryHelpers
23
+
24
+ # @return [Symbol]
25
+ attr_reader :name
26
+
27
+ # @param name [Symbol]
28
+ # @param attributes [Hash] These become attributes (with reader and writer
29
+ # methods) of the Plugin. It's really just a mechanism for defining
30
+ # available attributes and their default values.
31
+ def initialize(name, **attributes)
32
+ @name = name
33
+ @irb_configuration = nil
34
+
35
+ attributes.each do |k, v|
36
+ define_singleton_method(k) do
37
+ instance_variable_get("@#{k}".to_sym)
38
+ end
39
+
40
+ define_singleton_method("#{k}=") do |new_value|
41
+ instance_variable_set("@#{k}".to_sym, new_value)
42
+ end
43
+
44
+ instance_variable_set("@#{k}".to_sym, v)
45
+ end
46
+ end
47
+
48
+ # Everything in the +block+ given here will be the last code to get
49
+ # evaluated when #load! is called. This is where you define code that makes
50
+ # up your plugin.
51
+ def on_load(&block)
52
+ @on_load = block
53
+ end
54
+
55
+ # Loads the plugin using the +attributes+ values. The keys in +attributes+
56
+ # must match attributes that were given when the Plugin was defined.
57
+ # Attribute values given here will override the defaults that were given
58
+ # when the Plugin was defined.
59
+ def load!(**attributes)
60
+ attributes.each do |k, v|
61
+ send("#{k}=".to_sym, v)
62
+ end
63
+
64
+ require_libraries
65
+
66
+ if @on_load
67
+ if @on_load.kind_of?(Proc)
68
+ @on_load.call
69
+ else
70
+ fail PluginLoadFailure, self.name
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../../hairballs'
2
+
3
+ Hairballs.add_plugin(:awesome_print) do |plugin|
4
+ plugin.libraries %w(awesome_print)
5
+
6
+ plugin.on_load do
7
+ AwesomePrint.irb!
8
+ end
9
+ end
@@ -0,0 +1,30 @@
1
+ require_relative '../../hairballs'
2
+
3
+ # When any value is returned by evaluating some Ruby, this will check if it is
4
+ # JSON (by parsing it). If it's JSON-like, it will get formatted prettily and
5
+ # using the +color+ given when calling +Hairballs.load_plugin(:colorize_json)+.
6
+ #
7
+ # This *must* get used/loaded after the :wirble plugin to work.
8
+ #
9
+ # TODO: fix to work with using/loading before Wirble.
10
+ Hairballs.add_plugin(:colorize_json, color: :blue) do |plugin|
11
+ plugin.libraries %w(json colorize)
12
+
13
+ plugin.on_load do
14
+ IRB::Irb.class_eval do
15
+ alias_method :old_output_value, :output_value
16
+
17
+ define_method :output_value do
18
+ is_json = JSON.parse(@context.last_value) rescue nil
19
+
20
+ if is_json
21
+ vputs "[#{plugin.name}] Return value is JSON-like"
22
+ printf @context.return_format,
23
+ JSON.pretty_generate(JSON.parse(@context.last_value)).colorize(plugin.color)
24
+ else
25
+ old_output_value
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,22 @@
1
+ require_relative '../../hairballs'
2
+
3
+ # Returns only the methods not present on basic Objects.
4
+ #
5
+ # @see http://stackoverflow.com/a/873371/172106
6
+ Hairballs.add_plugin(:interesting_methods) do |plugin|
7
+ plugin.on_load do
8
+ Object.class_eval do
9
+ # @return [Array<Symbol>]
10
+ def interesting_methods
11
+ case self.class
12
+ when Class
13
+ public_methods.sort - Object.public_methods
14
+ when Module
15
+ public_methods.sort - Module.public_methods
16
+ else
17
+ public_methods.sort - Object.new.public_methods
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,37 @@
1
+ require_relative '../../hairballs'
2
+
3
+ Hairballs.add_plugin(:irb_history, save_history: 1000, eval_history: 20, global_history_file: true) do |plugin|
4
+ plugin.libraries %w(irb/ext/save-history)
5
+
6
+ plugin.on_load do
7
+ IRB.conf[:SAVE_HISTORY] = plugin.save_history
8
+ IRB.conf[:EVAL_HISTORY] = plugin.eval_history
9
+
10
+ unless plugin.global_history_file
11
+ IRB.conf[:HISTORY_FILE] = "#{Dir.home}/.irb_history-#{Hairballs.project_name}"
12
+ end
13
+
14
+ Object.class_eval do
15
+ # All of the ruby lines of code that have been executed.
16
+ def history
17
+ 0.upto(Readline::HISTORY.size - 1) do |i|
18
+ printf "%5d %s\n", i, Readline::HISTORY[i]
19
+ end
20
+ end
21
+
22
+ # Execute one or many lines of Ruby from +history+.
23
+ #
24
+ # @param command_numbers [Fixnum,Range]
25
+ def _!(command_numbers)
26
+ cmds =
27
+ if command_numbers.is_a? Range
28
+ command_numbers.to_a.map { |i| Readline::HISTORY[i] }
29
+ else
30
+ [Readline::HISTORY[command_numbers]]
31
+ end
32
+
33
+ cmds.each { |cmd| send(cmd) }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,20 @@
1
+ require_relative '../../hairballs'
2
+
3
+ # Directly lifted from rbates/dotfiles! Adds +#ri+ to all Objects, letting you
4
+ # get ri docs from within your IRB session.
5
+ Hairballs.add_plugin(:object_ri) do |plugin|
6
+ plugin.libraries %w(rdoc)
7
+
8
+ plugin.on_load do
9
+ Object.class_eval do
10
+ def ri(method=nil)
11
+ unless method && method =~ /^[A-Z]/ # if class isn't specified
12
+ klass = self.kind_of?(Class) ? name : self.class.name
13
+ method = [klass, method].compact.join('#')
14
+ end
15
+
16
+ system 'ri', method.to_s
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ require_relative '../../hairballs'
2
+
3
+ # Quick and dirty benchmarking of whatever block you pass to the method.
4
+ #
5
+ # @see http://stackoverflow.com/a/123834/172106
6
+ Hairballs.add_plugin(:quick_benchmark) do |plugin|
7
+ plugin.libraries %w(benchmark)
8
+
9
+ plugin.on_load do
10
+ Kernel.module_eval do
11
+ def quick_benchmark(repetitions=100, &block)
12
+ Benchmark.bmbm do |b|
13
+ b.report { repetitions.times(&block) }
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end