hairballs 0.0.1
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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/History.md +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +250 -0
- data/Rakefile +4 -0
- data/hairballs.gemspec +24 -0
- data/lib/hairballs/exceptions.rb +22 -0
- data/lib/hairballs/ext/kernel_vputs.rb +7 -0
- data/lib/hairballs/library_helpers.rb +85 -0
- data/lib/hairballs/plugin.rb +75 -0
- data/lib/hairballs/plugins/awesome_print.rb +9 -0
- data/lib/hairballs/plugins/colorize_json.rb +30 -0
- data/lib/hairballs/plugins/interesting_methods.rb +22 -0
- data/lib/hairballs/plugins/irb_history.rb +37 -0
- data/lib/hairballs/plugins/object_ri.rb +20 -0
- data/lib/hairballs/plugins/quick_benchmark.rb +18 -0
- data/lib/hairballs/plugins/require_project_lib.rb +17 -0
- data/lib/hairballs/plugins/tab_completion_for_files.rb +35 -0
- data/lib/hairballs/plugins/wirble.rb +11 -0
- data/lib/hairballs/prompt.rb +64 -0
- data/lib/hairballs/theme.rb +110 -0
- data/lib/hairballs/themes/turboladen.rb +34 -0
- data/lib/hairballs/themes/turboladen_rails.rb +33 -0
- data/lib/hairballs/version.rb +3 -0
- data/lib/hairballs.rb +113 -0
- data/spec/hairballs_spec.rb +185 -0
- data/spec/spec_helper.rb +64 -0
- metadata +118 -0
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
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/History.md
ADDED
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
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,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,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
|