hirb 0.1.2 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +16 -0
- data/README.rdoc +44 -108
- data/Rakefile +3 -2
- data/VERSION.yml +1 -1
- data/lib/hirb.rb +28 -3
- data/lib/hirb/console.rb +31 -5
- data/lib/hirb/formatter.rb +199 -0
- data/lib/hirb/helpers.rb +1 -1
- data/lib/hirb/helpers/active_record_table.rb +12 -3
- data/lib/hirb/helpers/auto_table.rb +3 -2
- data/lib/hirb/helpers/object_table.rb +4 -4
- data/lib/hirb/helpers/table.rb +89 -23
- data/lib/hirb/helpers/vertical_table.rb +31 -0
- data/lib/hirb/menu.rb +47 -0
- data/lib/hirb/pager.rb +94 -0
- data/lib/hirb/util.rb +53 -2
- data/lib/hirb/view.rb +116 -140
- data/test/active_record_table_test.rb +35 -0
- data/test/auto_table_test.rb +20 -0
- data/test/console_test.rb +12 -0
- data/test/formatter_test.rb +172 -0
- data/test/menu_test.rb +94 -0
- data/test/object_table_test.rb +49 -0
- data/test/pager_test.rb +164 -0
- data/test/table_test.rb +82 -52
- data/test/test_helper.rb +41 -0
- data/test/util_test.rb +53 -18
- data/test/view_test.rb +98 -151
- metadata +37 -15
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
== 0.2.2
|
2
|
+
* Added a friendlier default (a vertical table) to incorrectly configured tables.
|
3
|
+
* Added vertical table helper thanks to chrononaut.
|
4
|
+
* Added detection of :select option from ActiveRecord queries in ActiveRecordTable helper.
|
5
|
+
* Added handling anything that responds to :to_a in AutoTable helper.
|
6
|
+
|
7
|
+
== 0.2.1
|
8
|
+
* Fixed typo in Hirb::Console.view
|
9
|
+
|
10
|
+
== 0.2.0
|
11
|
+
* Major refactoring with bug fixes and better tests.
|
12
|
+
* Improved table algorithm to ensure that tables don't wrap.
|
13
|
+
* Added a pager which detects if output should be paged, Hirb::Pager.
|
14
|
+
* Added a selection menu, Hirb::Menu
|
15
|
+
* Following API changes: Hirb::Helpers::Table.max_width removed and config files don't use
|
16
|
+
the :view key anymore.
|
1
17
|
== 0.1.2
|
2
18
|
* Added tree views.
|
3
19
|
* Added output_method option to Hirb::View.render_output.
|
data/README.rdoc
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
== Description
|
2
2
|
|
3
|
-
Hirb currently provides a mini view framework for console applications, designed
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
Hirb currently provides a mini view framework for console applications, designed to improve irb's default output.
|
4
|
+
Hirb improves console output by providing a smart pager and auto-formatting output. The smart pager detects when an output exceeds
|
5
|
+
a screenful and thus only pages output as needed. Auto-formatting adds a view to an output's class. This is helpful in separating
|
6
|
+
views from content (MVC anyone?). The framework encourages reusing views by letting you
|
7
|
+
package them in classes and associate them with any number of output classes. Hirb comes with tree views (see
|
7
8
|
Hirb::Helpers::Tree) and table views (see Hirb::Helpers::Table). By default Hirb displays Rails'
|
8
|
-
model classes as tables.
|
9
|
+
model classes as tables. Hirb also sports a nice selection menu, Hirb::Menu.
|
9
10
|
|
10
11
|
== Install
|
11
12
|
|
@@ -13,19 +14,36 @@ Install the gem with:
|
|
13
14
|
|
14
15
|
sudo gem install cldwalker-hirb --source http://gems.github.com
|
15
16
|
|
16
|
-
==
|
17
|
+
== Pager
|
18
|
+
|
19
|
+
Hirb has both pager and formatter functionality enabled by default.
|
20
|
+
If you want to turn off the functionality of either you can pass that in at startup:
|
21
|
+
|
22
|
+
Hirb.enable :pager=>false
|
23
|
+
Hirb.enable :formatter=>false
|
24
|
+
|
25
|
+
or toggle their state at runtime:
|
26
|
+
|
27
|
+
Hirb::View.toggle_pager
|
28
|
+
Hirb::View.toggle_formatter
|
29
|
+
|
30
|
+
== Create and Configure Views
|
31
|
+
|
32
|
+
If you'd like to learn how to create and configure views, {read the docs}[http://tagaholic.me/hirb/doc/classes/Hirb/Formatter.html].
|
33
|
+
|
34
|
+
== Rails Formatter Example
|
17
35
|
|
18
36
|
Let's load and enable the view framework:
|
19
37
|
bash> script/console
|
20
38
|
Loading local environment (Rails 2.2.2)
|
21
39
|
irb>> require 'hirb'
|
22
40
|
=> true
|
23
|
-
irb>> Hirb
|
41
|
+
irb>> Hirb.enable
|
24
42
|
=> nil
|
25
43
|
|
26
44
|
The default configuration provides table views for ActiveRecord::Base descendants.
|
27
45
|
If a class isn't configured, Hirb reverts to irb's default echo mode.
|
28
|
-
irb>> Hirb::View.
|
46
|
+
irb>> Hirb::View.formatter_config
|
29
47
|
=> {"ActiveRecord::Base"=>{:class=>"Hirb::Views::ActiveRecord_Base", :ancestor=>true}}
|
30
48
|
|
31
49
|
# Tag is a model class and descendant of ActiveRecord::Base
|
@@ -60,7 +78,7 @@ you may appreciate it also detects configured output objects in an array:
|
|
60
78
|
3 rows in set
|
61
79
|
|
62
80
|
At any time you can disable Hirb if you really like irb's lovely echo mode:
|
63
|
-
irb>> Hirb
|
81
|
+
irb>> Hirb.disable
|
64
82
|
=> nil
|
65
83
|
irb>> Tag.all :limit=>3, :order=>"id DESC"
|
66
84
|
=> [#<Tag id: 907, name: "gem:tags=yaml", description: nil, created_at: "2009-03-06 21:10:41",
|
@@ -74,7 +92,7 @@ While preconfigured tables are great for database records, sometimes you just wa
|
|
74
92
|
tables/views for any output object:
|
75
93
|
|
76
94
|
#These examples don't need to have Hirb::View enabled.
|
77
|
-
irb>>Hirb
|
95
|
+
irb>>Hirb.disable
|
78
96
|
=>nil
|
79
97
|
|
80
98
|
# Imports table() and view()
|
@@ -91,8 +109,8 @@ tables/views for any output object:
|
|
91
109
|
+------------+--------+-----------+-------+--------------------------+
|
92
110
|
2 rows in set
|
93
111
|
|
94
|
-
# Same table as the previous method. However view() will be able to call any
|
95
|
-
irb>> view [Date.today, Date.today.next_month], :class
|
112
|
+
# Same table as the previous method. However view() will be able to call any helper.
|
113
|
+
irb>> view [Date.today, Date.today.next_month], :class=>:object_table,
|
96
114
|
:fields=>[:to_s, :ld, :ajd, :amjd, :asctime]
|
97
115
|
|
98
116
|
If these console methods weren't convenient enough, try:
|
@@ -101,7 +119,7 @@ If these console methods weren't convenient enough, try:
|
|
101
119
|
irb>> require 'hirb/import_object'
|
102
120
|
=>true
|
103
121
|
# Yields same table as above examples.
|
104
|
-
irb>> [Date.today, Date.today.next_month].view :class
|
122
|
+
irb>> [Date.today, Date.today.next_month].view :class=>:object_table,
|
105
123
|
:fields=>[:to_s, :ld, :ajd, :amjd, :asctime]
|
106
124
|
|
107
125
|
Although views by default are printed to STDOUT, they can be easily modified to write anywhere:
|
@@ -109,7 +127,7 @@ Although views by default are printed to STDOUT, they can be easily modified to
|
|
109
127
|
irb>> Hirb::View.render_method = lambda {|output| File.open("console.log", 'w') {|f| f.write(output) } }
|
110
128
|
|
111
129
|
# Writes to file with same table output as above example.
|
112
|
-
irb>> view [Date.today, Date.today.next_month], :class
|
130
|
+
irb>> view [Date.today, Date.today.next_month], :class=>:object_table,
|
113
131
|
:fields=>[:to_s, :ld, :ajd, :amjd, :asctime]
|
114
132
|
|
115
133
|
# Doesn't write to file because Symbol isn't configured to use Hirb::View and thus defaults to irb's echo mode.
|
@@ -119,113 +137,31 @@ Although views by default are printed to STDOUT, they can be easily modified to
|
|
119
137
|
# Go back to printing Hirb views to STDOUT.
|
120
138
|
irb>> Hirb::View.reset_render_method
|
121
139
|
|
122
|
-
==
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
irb>> require 'hirb'
|
127
|
-
=>true
|
128
|
-
irb>> Hirb::View.enable
|
129
|
-
=>nil
|
130
|
-
irb>> require 'yaml'
|
131
|
-
=>true
|
132
|
-
|
133
|
-
=== Configure As View Method
|
134
|
-
A view method is the smallest reuseable view.
|
135
|
-
# Create yaml view method
|
136
|
-
irb>> def yaml(output); output.to_yaml; end
|
137
|
-
=>nil
|
138
|
-
|
139
|
-
# Configure view and reload it
|
140
|
-
irb>>Hirb::View.output_config = {"Hash"=>{:method=>:yaml}}
|
141
|
-
=>{"Hash"=>{:method=>:yaml}}
|
142
|
-
irb>>Hash::View.reload_config
|
143
|
-
=>true
|
144
|
-
|
145
|
-
# Hashes now appear as yaml
|
146
|
-
irb>>{:a=>1, :b=>{:c=>3}}
|
147
|
-
---
|
148
|
-
:a : 1
|
149
|
-
:b :
|
150
|
-
:c : 3
|
151
|
-
=> true
|
152
|
-
|
153
|
-
=== Configure As View Class
|
154
|
-
A view class is suited for more complex views. View classes can be under any namespace
|
155
|
-
and are expected to provide a render method. However, if a class is under the Hirb::Views namespace,
|
156
|
-
it will be automatically loaded with no configuration. Something to think about when
|
157
|
-
sharing views with others.
|
158
|
-
|
159
|
-
# Create yaml view class
|
160
|
-
irb>> class Hirb::Views::Hash; def self.render(output, options={}); output.to_yaml; end ;end
|
161
|
-
=>nil
|
162
|
-
# Just reload since no configuration is necessary
|
163
|
-
irb>>Hirb::View.reload_config
|
164
|
-
|
165
|
-
# Hashes now appear as yaml ...
|
166
|
-
|
167
|
-
Although the Hirb::Views namespace is great for quick classes that just plug and play, you
|
168
|
-
often want view classes that can be reused with multiple outputs. For this case, it's recommended to
|
169
|
-
use the Hirb::Helpers namespace.
|
170
|
-
|
171
|
-
# Create yaml view class
|
172
|
-
irb>> class Hirb::Helpers::Yaml; def self.render(output, options={}); output.to_yaml; end ;end
|
173
|
-
=>nil
|
174
|
-
|
175
|
-
# Configure view and reload it
|
176
|
-
irb>>Hirb::View.output_config = {"Hash"=>{:class=>"Hirb::Helpers::Yaml"}}
|
177
|
-
=>{"Hash"=>{:class=>"Hirb::Helpers::Yaml"}}
|
178
|
-
irb>>Hirb::View.reload_config
|
179
|
-
|
180
|
-
# Hashes now appear as yaml ...
|
181
|
-
|
182
|
-
=== Configure At Startup
|
183
|
-
Once you know what views are associated with what output classes, you can configure
|
184
|
-
them at startup by passing Hirb::View.enable a block:
|
185
|
-
# In .irbrc
|
186
|
-
require 'hirb'
|
187
|
-
# View class needs to come before enable()
|
188
|
-
class Hirb::Helpers::Yaml; def self.render(output, options={}); output.to_yaml; end ;end
|
189
|
-
Hirb::View.enable {|conf| conf.output = {"Hash"=>{:class=>"Hirb::Helpers::Yaml"}} }
|
190
|
-
|
191
|
-
Or by creating a config file at config/hirb.yml or ~/.hirb.yml:
|
192
|
-
# The config file for the yaml example would look like:
|
193
|
-
# ---
|
194
|
-
# :view :
|
195
|
-
# :output :
|
196
|
-
# Hash :
|
197
|
-
# :class : Hirb::Helpers::Yaml
|
198
|
-
|
199
|
-
# In .irbrc
|
200
|
-
require 'hirb'
|
201
|
-
# View class needs to come before enable()
|
202
|
-
class Hirb::Helpers::Yaml; def self.render(output, options={}); output.to_yaml; end ;end
|
203
|
-
Hirb::View.enable
|
204
|
-
|
205
|
-
== Contributing Views
|
206
|
-
If you have views of your own you'd like to share, fork Hirb and put your views under
|
207
|
-
the Hirb::Helpers namespace and the view files under lib/hirb/helpers/.
|
140
|
+
== Sharing Views
|
141
|
+
If you have tested views you'd like to share, fork Hirb and put your views under
|
142
|
+
the lib/hirb/views/ and/or helpers files under lib/hirb/helpers/. If not tested, feel free to share
|
143
|
+
them on the wiki.
|
208
144
|
|
209
145
|
== Limitations
|
210
|
-
|
211
|
-
This is mainly because colorizing caused table classes to render incorrectly. If you can get tables
|
212
|
-
and colors to work nicely, please fork. To colorize your Hirb output:
|
213
|
-
Hirb::View.render_method = lambda {|output| puts Wirble::Colorize.colorize(output) }
|
146
|
+
If using Wirble, you should call Hirb after it since they both override irb's default output.
|
214
147
|
|
215
148
|
== Motivation
|
216
149
|
Table code from http://gist.github.com/72234 and {my console
|
217
150
|
app's needs}[http://github.com/cldwalker/tag-tree].
|
218
151
|
|
219
|
-
==
|
220
|
-
|
152
|
+
== Credits
|
153
|
+
Chrononaut for vertical table helper.
|
154
|
+
|
155
|
+
== Bugs/Issues
|
156
|
+
Please report them {on github}[http://github.com/cldwalker/hirb/issues].
|
221
157
|
|
222
158
|
== Links
|
223
159
|
* http://tagaholic.me/2009/03/13/hirb-irb-on-the-good-stuff.html
|
224
160
|
* http://tagaholic.me/2009/03/18/ruby-class-trees-rails-plugin-trees-with-hirb.html
|
161
|
+
* http://tagaholic.me/2009/06/19/page-irb-output-and-improve-ri-with-hirb.html
|
225
162
|
|
226
163
|
== Todo
|
227
|
-
* Configurable max height, which if exceeded activates a pager.
|
228
|
-
* Possibly add non-view irb goodies ie command manager.
|
229
164
|
* Consider applying multiple views/filters to output.
|
165
|
+
* Consider mapping a class' methods to their own views.
|
230
166
|
* Provides helper methods to all view classes.
|
231
167
|
* Consider adding a template system as needed.
|
data/Rakefile
CHANGED
@@ -18,11 +18,12 @@ begin
|
|
18
18
|
require 'jeweler'
|
19
19
|
Jeweler::Tasks.new do |s|
|
20
20
|
s.name = "hirb"
|
21
|
-
s.
|
22
|
-
s.
|
21
|
+
s.summary = "A mini view framework for console/irb that's easy to use, even while under its influence."
|
22
|
+
s.description = "Hirb currently provides a mini view framework for console applications, designed to improve irb's default output. Hirb improves console output by providing a smart pager and auto-formatting output. The smart pager detects when an output exceeds a screenful and thus only pages output as needed. Auto-formatting adds a view to an output's class. This is helpful in separating views from content (MVC anyone?). The framework encourages reusing views by letting you package them in classes and associate them with any number of output classes."
|
23
23
|
s.email = "gabriel.horner@gmail.com"
|
24
24
|
s.homepage = "http://github.com/cldwalker/hirb"
|
25
25
|
s.authors = ["Gabriel Horner"]
|
26
|
+
s.rubyforge_project = 'tagaholic'
|
26
27
|
s.has_rdoc = true
|
27
28
|
s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
|
28
29
|
s.files = FileList["[A-Z]*", "{bin,lib,test}/**/*"]
|
data/VERSION.yml
CHANGED
data/lib/hirb.rb
CHANGED
@@ -6,19 +6,44 @@ require 'hirb/helpers'
|
|
6
6
|
require 'hirb/view'
|
7
7
|
require 'hirb/views/activerecord_base'
|
8
8
|
require 'hirb/console'
|
9
|
+
require 'hirb/formatter'
|
10
|
+
require 'hirb/pager'
|
11
|
+
require 'hirb/menu'
|
9
12
|
|
10
13
|
# Most of Hirb's functionality currently resides in Hirb::View.
|
11
|
-
#
|
14
|
+
# For an in-depth tutorial on creating and configuring views see Hirb::Formatter.
|
15
|
+
# Hirb has an optional yaml config file defined by config_file(). This config file
|
12
16
|
# has the following top level keys:
|
13
|
-
# [:
|
17
|
+
# [:output] This hash is used by the formatter object. See Hirb::Formatter.config for its format.
|
18
|
+
# [:width] Width of the terminal/console. Defaults to DEFAULT_WIDTH or possibly autodetected when Hirb is enabled.
|
19
|
+
# [:height] Height of the terminal/console. Defaults to DEFAULT_HEIGHT or possibly autodetected when Hirb is enabled.
|
20
|
+
# [:formatter] Boolean which determines if the formatter is enabled. Defaults to true.
|
21
|
+
# [:pager] Boolean which determines if the pager is enabled. Defaults to true.
|
22
|
+
# [:pager_command] Command to be used for paging. Command can have options after it i.e. 'less -r'.
|
23
|
+
# Defaults to common pagers i.e. less and more if detected.
|
24
|
+
#
|
25
|
+
|
14
26
|
module Hirb
|
15
27
|
class <<self
|
28
|
+
# Enables view functionality. See Hirb::View.enable for details.
|
29
|
+
def enable(options={}, &block)
|
30
|
+
View.enable(options, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Disables view functionality. See Hirb::View.disable for details.
|
34
|
+
def disable
|
35
|
+
View.disable
|
36
|
+
end
|
16
37
|
# Default is config/hirb.yml or ~/hirb.yml in that order.
|
17
38
|
def config_file
|
18
|
-
File.exists?('config/hirb.yml') ? 'config/hirb.yml' : File.expand_path(File.join("
|
39
|
+
@config_file ||= File.exists?('config/hirb.yml') ? 'config/hirb.yml' : File.expand_path(File.join(ENV["HOME"],".hirb.yml"))
|
19
40
|
end
|
20
41
|
|
21
42
|
#:stopdoc:
|
43
|
+
def config_file=(value)
|
44
|
+
@config_file = value
|
45
|
+
end
|
46
|
+
|
22
47
|
def read_config_file(file=config_file)
|
23
48
|
File.exists?(file) ? YAML::load_file(file) : {}
|
24
49
|
end
|
data/lib/hirb/console.rb
CHANGED
@@ -1,17 +1,43 @@
|
|
1
1
|
module Hirb
|
2
|
-
# This
|
2
|
+
# This module is meant to be extended to provide methods for use in a console/irb shell.
|
3
3
|
# For example:
|
4
4
|
# irb>> extend Hirb::Console
|
5
5
|
# irb>> view 'some string', :class=>Some::String::Formatter
|
6
6
|
# irb>> table [[:row1], [:row2]]
|
7
7
|
module Console
|
8
|
+
class<<self
|
9
|
+
# A console version of render_output() which takes its same options but allows for shorthand. All options are passed to
|
10
|
+
# the helper except for the formatter options. Formatter options are :class, :method and :output_method.
|
11
|
+
# Examples:
|
12
|
+
# render_output output, :class=>:tree :type=>:directory
|
13
|
+
# # is the same as:
|
14
|
+
# render_output output, :class=>:tree, :options=> {:type=>:directory}
|
15
|
+
#
|
16
|
+
def render_output(output, options={})
|
17
|
+
View.load_config unless View.config_loaded?
|
18
|
+
View.render_output(output, options.merge(:console=>true))
|
19
|
+
end
|
20
|
+
|
21
|
+
# Takes same arguments and options as render_output() but returns formatted output instead of rendering it.
|
22
|
+
def format_output(output, options={}, &block)
|
23
|
+
View.load_config unless View.config_loaded?
|
24
|
+
View.formatter.format_output(output, options.merge(:console=>true), &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
8
28
|
# Renders a table for the given object. Takes same options as Hirb::Helpers::Table.render.
|
9
29
|
def table(output, options={})
|
10
|
-
|
30
|
+
Console.render_output(output, options.merge(:class=>"Hirb::Helpers::AutoTable"))
|
31
|
+
end
|
32
|
+
|
33
|
+
# Renders any specified view for the given object. Takes same options as Hirb::View.render_output.
|
34
|
+
def view(output, options={})
|
35
|
+
Console.render_output(output, options)
|
11
36
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
37
|
+
|
38
|
+
# Renders a menu given an array using Hirb::Menu.render.
|
39
|
+
def menu(output, options={}, &block)
|
40
|
+
Console.format_output(output, options.merge(:class=>"Hirb::Menu"), &block)
|
15
41
|
end
|
16
42
|
end
|
17
43
|
end
|
@@ -0,0 +1,199 @@
|
|
1
|
+
module Hirb
|
2
|
+
=begin rdoc
|
3
|
+
This class is format an output into a string using Hirb::Helpers::*, Hirb::Views::* or any user-created views.
|
4
|
+
The formatter object looks for an output's class config in Hirb::Formatter.config and if found applies a helper to the output.
|
5
|
+
|
6
|
+
== Create and Configure Views
|
7
|
+
Let's create a simple view and configure it in different ways to be Hash's default view:
|
8
|
+
|
9
|
+
=== Setup
|
10
|
+
irb>> require 'hirb'
|
11
|
+
=>true
|
12
|
+
irb>> Hirb.enable
|
13
|
+
=>nil
|
14
|
+
irb>> require 'yaml'
|
15
|
+
=>true
|
16
|
+
|
17
|
+
=== Configure As View Method
|
18
|
+
A view method is the smallest reuseable view.
|
19
|
+
# Create yaml view method
|
20
|
+
irb>> def yaml(output); output.to_yaml; end
|
21
|
+
=>nil
|
22
|
+
|
23
|
+
# Configure view
|
24
|
+
irb>>Hirb::View.format_class Hash, :method=>:yaml
|
25
|
+
=>true
|
26
|
+
|
27
|
+
# Hashes now appear as yaml
|
28
|
+
irb>>{:a=>1, :b=>{:c=>3}}
|
29
|
+
---
|
30
|
+
:a : 1
|
31
|
+
:b :
|
32
|
+
:c : 3
|
33
|
+
=> true
|
34
|
+
|
35
|
+
=== Configure As View Class
|
36
|
+
A view class is suited for more complex views. View classes can be under any namespace
|
37
|
+
and are expected to provide a render method. However, if a class is under the Hirb::Views namespace,
|
38
|
+
it will be automatically loaded with no configuration. Something to think about when
|
39
|
+
sharing views with others.
|
40
|
+
|
41
|
+
# Create yaml view class
|
42
|
+
irb>> class Hirb::Views::Hash; def self.render(output, options={}); output.to_yaml; end ;end
|
43
|
+
=>nil
|
44
|
+
# Just reload since no configuration is necessary
|
45
|
+
irb>>Hirb::View.formatter.reload
|
46
|
+
|
47
|
+
# Hashes now appear as yaml ...
|
48
|
+
|
49
|
+
Although the Hirb::Views namespace is great for quick classes that just plug and play, you
|
50
|
+
often want view classes that can be reused with multiple outputs. For this case, it's recommended to
|
51
|
+
use the Hirb::Helpers namespace.
|
52
|
+
|
53
|
+
# Create yaml view class
|
54
|
+
irb>> class Hirb::Helpers::Yaml; def self.render(output, options={}); output.to_yaml; end ;end
|
55
|
+
=>nil
|
56
|
+
|
57
|
+
# Configure view and reload it
|
58
|
+
irb>>Hirb::View.format_class Hash, :class=>"Hirb::Helpers::Yaml"
|
59
|
+
=>true
|
60
|
+
|
61
|
+
# Hashes now appear as yaml ...
|
62
|
+
|
63
|
+
== Configure At Startup
|
64
|
+
Once you know what views are associated with what output classes, you can configure
|
65
|
+
them at startup by passing Hirb.enable an options hash:
|
66
|
+
# In .irbrc
|
67
|
+
require 'hirb'
|
68
|
+
# View class needs to come before enable()
|
69
|
+
class Hirb::Helpers::Yaml; def self.render(output, options={}); output.to_yaml; end ;end
|
70
|
+
Hirb.enable :output=>{"Hash"=>{:class=>"Hirb::Helpers::Yaml"}}
|
71
|
+
|
72
|
+
Or by creating a config file at config/hirb.yml or ~/.hirb.yml:
|
73
|
+
# The config file for the yaml example would look like:
|
74
|
+
# ---
|
75
|
+
# :output :
|
76
|
+
# Hash :
|
77
|
+
# :class : Hirb::Helpers::Yaml
|
78
|
+
|
79
|
+
# In .irbrc
|
80
|
+
require 'hirb'
|
81
|
+
# View class needs to come before enable()
|
82
|
+
class Hirb::Helpers::Yaml; def self.render(output, options={}); output.to_yaml; end ;end
|
83
|
+
Hirb.enable
|
84
|
+
=end
|
85
|
+
|
86
|
+
class Formatter
|
87
|
+
def initialize(additional_config={})
|
88
|
+
@klass_config = {}
|
89
|
+
@config = Util.recursive_hash_merge default_config, additional_config || {}
|
90
|
+
end
|
91
|
+
|
92
|
+
# A hash of Ruby class strings mapped to helper config hashes. A helper config hash must have at least a :method, :output_method
|
93
|
+
# or :class option for a helper to be applied to an output. A helper config hash has the following keys:
|
94
|
+
# [:method] Specifies a global (Kernel) method to do the formatting.
|
95
|
+
# [:class] Specifies a class to do the formatting, using its render() class method. If a symbol it's converted to a corresponding
|
96
|
+
# Hirb::Helpers::* class if it exists.
|
97
|
+
# [:output_method] Specifies a method or proc to call on output before passing it to a helper. If the output is an array, it's applied
|
98
|
+
# to every element in the array.
|
99
|
+
# [:options] Options to pass the helper method or class.
|
100
|
+
# [:ancestor] Boolean which when true causes subclasses of the output class to inherit its config. This doesn't effect the current
|
101
|
+
# output class. Defaults to false. This is used by ActiveRecord classes.
|
102
|
+
#
|
103
|
+
# Examples:
|
104
|
+
# {'WWW::Delicious::Element'=>{:class=>'Hirb::Helpers::ObjectTable', :ancestor=>true, :options=>{:max_width=>180}}}
|
105
|
+
# {'Date'=>{:class=>:auto_table, :ancestor=>true}}
|
106
|
+
def config
|
107
|
+
@config
|
108
|
+
end
|
109
|
+
|
110
|
+
# Sets the helper config for the given output class.
|
111
|
+
def format_class(klass, helper_config)
|
112
|
+
@klass_config.delete(klass)
|
113
|
+
@config[klass.to_s] = helper_config
|
114
|
+
true
|
115
|
+
end
|
116
|
+
|
117
|
+
# Reloads autodetected Hirb::Views
|
118
|
+
def reload
|
119
|
+
@config = Util.recursive_hash_merge default_config, @config
|
120
|
+
end
|
121
|
+
|
122
|
+
# This is the main method of this class. The formatter looks for the first helper in its config for the given output class.
|
123
|
+
# If a helper is found, the output is converted by the helper into a string and returned. If not, nil is returned. The options
|
124
|
+
# this class takes are a helper config hash as described in config. These options will be merged with any existing helper config hash
|
125
|
+
# an output class has in config. Any block given is passed along to a helper class.
|
126
|
+
def format_output(output, options={}, &block)
|
127
|
+
output_class = determine_output_class(output)
|
128
|
+
options = parse_console_options(options) if options.delete(:console)
|
129
|
+
options = Util.recursive_hash_merge(klass_config(output_class), options)
|
130
|
+
output = options[:output_method] ? (output.is_a?(Array) ? output.map {|e| call_output_method(options[:output_method], e) } :
|
131
|
+
call_output_method(options[:output_method], output) ) : output
|
132
|
+
args = [output]
|
133
|
+
args << options[:options] if options[:options] && !options[:options].empty?
|
134
|
+
if options[:method]
|
135
|
+
new_output = send(options[:method],*args)
|
136
|
+
elsif options[:class] && (helper_class = determine_helper_class(options[:class]))
|
137
|
+
new_output = helper_class.render(*args, &block)
|
138
|
+
elsif options[:output_method]
|
139
|
+
new_output = output
|
140
|
+
end
|
141
|
+
new_output
|
142
|
+
end
|
143
|
+
|
144
|
+
#:stopdoc:
|
145
|
+
def parse_console_options(options) #:nodoc:
|
146
|
+
real_options = [:method, :class, :output_method].inject({}) do |h, e|
|
147
|
+
h[e] = options.delete(e) if options[e]; h
|
148
|
+
end
|
149
|
+
real_options.merge! :options=>options
|
150
|
+
real_options
|
151
|
+
end
|
152
|
+
|
153
|
+
def determine_helper_class(klass)
|
154
|
+
if klass.is_a?(Symbol) && (helper_class = Helpers.constants.find {|e| e == Util.camelize(klass.to_s)})
|
155
|
+
klass = "Hirb::Helpers::#{helper_class}"
|
156
|
+
end
|
157
|
+
Util.any_const_get(klass)
|
158
|
+
end
|
159
|
+
|
160
|
+
def determine_output_class(output)
|
161
|
+
if output.is_a?(Array)
|
162
|
+
output[0].class
|
163
|
+
else
|
164
|
+
output.class
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def call_output_method(output_method, output)
|
169
|
+
output_method.is_a?(Proc) ? output_method.call(output) : output.send(output_method)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Internal view options built from user-defined ones. Options are built by recursively merging options from oldest
|
173
|
+
# ancestors to the most recent ones.
|
174
|
+
def klass_config(output_class)
|
175
|
+
@klass_config[output_class] ||= begin
|
176
|
+
output_ancestors_with_config = output_class.ancestors.map {|e| e.to_s}.select {|e| @config.has_key?(e)}
|
177
|
+
@klass_config[output_class] = output_ancestors_with_config.reverse.inject({}) {|h, klass|
|
178
|
+
(klass == output_class.to_s || @config[klass][:ancestor]) ? h.update(@config[klass]) : h
|
179
|
+
}
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def reset_klass_config
|
184
|
+
@klass_config = {}
|
185
|
+
end
|
186
|
+
|
187
|
+
def default_config
|
188
|
+
Views.constants.inject({}) {|h,e|
|
189
|
+
output_class = e.to_s.gsub("_", "::")
|
190
|
+
if (views_class = Views.const_get(e)) && views_class.respond_to?(:render)
|
191
|
+
default_options = views_class.respond_to?(:default_options) ? views_class.default_options : {}
|
192
|
+
h[output_class] = default_options.merge({:class=>"Hirb::Views::#{e}"})
|
193
|
+
end
|
194
|
+
h
|
195
|
+
}
|
196
|
+
end
|
197
|
+
#:startdoc:
|
198
|
+
end
|
199
|
+
end
|