hirb 0.2.10 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +14 -0
- data/README.rdoc +67 -63
- data/Rakefile +3 -0
- data/lib/hirb.rb +25 -18
- data/lib/hirb/console.rb +3 -3
- data/lib/hirb/dynamic_view.rb +112 -0
- data/lib/hirb/formatter.rb +61 -140
- data/lib/hirb/helpers.rb +11 -1
- data/lib/hirb/helpers/auto_table.rb +20 -12
- data/lib/hirb/helpers/object_table.rb +2 -2
- data/lib/hirb/helpers/table.rb +15 -14
- data/lib/hirb/helpers/tree.rb +19 -15
- data/lib/hirb/import_object.rb +1 -1
- data/lib/hirb/menu.rb +1 -1
- data/lib/hirb/util.rb +1 -1
- data/lib/hirb/version.rb +3 -0
- data/lib/hirb/view.rb +74 -19
- data/lib/hirb/views.rb +8 -0
- data/lib/hirb/views/couch_db.rb +11 -0
- data/lib/hirb/views/misc_db.rb +15 -0
- data/lib/hirb/views/mongo_db.rb +15 -0
- data/lib/hirb/views/orm.rb +11 -0
- data/lib/hirb/views/rails.rb +19 -0
- data/test/dynamic_view_test.rb +96 -0
- data/test/formatter_test.rb +36 -48
- data/test/table_test.rb +41 -4
- data/test/tree_test.rb +17 -0
- data/test/view_test.rb +6 -0
- data/test/views_test.rb +15 -0
- metadata +24 -11
- data/VERSION.yml +0 -5
- data/lib/hirb/hash_struct.rb +0 -17
- data/lib/hirb/helpers/active_record_table.rb +0 -26
- data/lib/hirb/views/activerecord_base.rb +0 -9
- data/test/active_record_table_test.rb +0 -35
data/lib/hirb/helpers.rb
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
module Hirb
|
2
2
|
module Helpers #:nodoc:
|
3
|
+
@helper_classes ||= {}
|
4
|
+
def self.helper_class(klass)
|
5
|
+
@helper_classes[klass.to_s] ||= begin
|
6
|
+
if (helper_class = constants.find {|e| e.to_s == Util.camelize(klass.to_s)})
|
7
|
+
klass = "Hirb::Helpers::#{helper_class}"
|
8
|
+
end
|
9
|
+
Util.any_const_get(klass)
|
10
|
+
end
|
11
|
+
end
|
3
12
|
end
|
4
13
|
end
|
5
|
-
|
14
|
+
|
15
|
+
%w{table object_table auto_table tree parent_child_tree vertical_table}.each do |e|
|
6
16
|
require "hirb/helpers/#{e}"
|
7
17
|
end
|
@@ -1,16 +1,24 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
1
|
+
# This helper wraps around the other table helpers i.e. Hirb::Helpers::Table while
|
2
|
+
# providing default helper options via Hirb::DynamicView. Using these default options, this
|
3
|
+
# helper supports views for the following modules/classes:
|
4
|
+
# ActiveRecord::Base, CouchFoo::Base, CouchPotato::Persistence, CouchRest::ExtendedDocument,
|
5
|
+
# DBI::Row, DataMapper::Resource, Friendly::Document, MongoMapper::Document, MongoMapper::EmbeddedDocument,
|
6
|
+
# Mongoid::Document, Ripple::Document, Sequel::Model.
|
7
|
+
class Hirb::Helpers::AutoTable < Hirb::Helpers::Table
|
8
|
+
extend Hirb::DynamicView
|
9
|
+
|
10
|
+
# Takes same options as Hirb::Helpers::Table.render except as noted below.
|
11
|
+
#
|
12
|
+
# ==== Options:
|
13
|
+
# [:table_class] Explicit table class to use for rendering. Defaults to
|
14
|
+
# Hirb::Helpers::ObjectTable if output is not an Array or Hash. Otherwise
|
15
|
+
# defaults to Hirb::Helpers::Table.
|
4
16
|
def self.render(output, options={})
|
5
|
-
options[:_original_class] = output.class
|
6
17
|
output = Array(output)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
Hirb::Helpers::ObjectTable
|
11
|
-
else
|
12
|
-
Hirb::Helpers::Table
|
13
|
-
end
|
18
|
+
(defaults = dynamic_options(output[0])) && (options = defaults.merge(options))
|
19
|
+
klass = options.delete(:table_class) || (
|
20
|
+
!(output[0].is_a?(Hash) || output[0].is_a?(Array)) ?
|
21
|
+
Hirb::Helpers::ObjectTable : Hirb::Helpers::Table)
|
14
22
|
klass.render(output, options)
|
15
23
|
end
|
16
|
-
end
|
24
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class Hirb::Helpers::ObjectTable < Hirb::Helpers::Table
|
2
2
|
# Rows are any ruby objects. Takes same options as Hirb::Helpers::Table.render except as noted below.
|
3
3
|
#
|
4
|
-
# Options:
|
5
|
-
#
|
4
|
+
# ==== Options:
|
5
|
+
# [:fields] Methods of the object to represent as columns. Defaults to [:to_s].
|
6
6
|
def self.render(rows, options ={})
|
7
7
|
options[:fields] ||= [:to_s]
|
8
8
|
options[:headers] ||= {:to_s=>'value'} if options[:fields] == [:to_s]
|
data/lib/hirb/helpers/table.rb
CHANGED
@@ -68,7 +68,7 @@ module Hirb
|
|
68
68
|
# ==== Options:
|
69
69
|
# [*:fields*] An array which overrides the default fields and can be used to indicate field order.
|
70
70
|
# [*:headers*] A hash of fields and their header names. Fields that aren't specified here default to their name.
|
71
|
-
#
|
71
|
+
# When set to false, headers are hidden. Can also be an array but only for array rows.
|
72
72
|
# [*:max_fields*] A hash of fields and their maximum allowed lengths. Maximum length can also be a percentage of the total width
|
73
73
|
# (decimal less than one). When a field exceeds it's maximum then it's
|
74
74
|
# truncated and has a ... appended to it. Fields that aren't specified have no maximum.
|
@@ -90,7 +90,6 @@ module Hirb
|
|
90
90
|
# [*:description*] When set to true, renders row count description at bottom. Default is true.
|
91
91
|
# [*:escape_special_chars*] When set to true, escapes special characters \n,\t,\r so they don't disrupt tables. Default is false for
|
92
92
|
# vertical tables and true for anything else.
|
93
|
-
# [*:return_rows*] When set to true, returns rows that have been initialized but not rendered. Default is false.
|
94
93
|
# Examples:
|
95
94
|
# Hirb::Helpers::Table.render [[1,2], [2,3]]
|
96
95
|
# Hirb::Helpers::Table.render [[1,2], [2,3]], :max_fields=>{0=>10}, :header_filter=>:capitalize
|
@@ -100,7 +99,7 @@ module Hirb
|
|
100
99
|
# Hirb::Helpers::Table.render [{:age=>10, :weight=>100}, {:age=>80, :weight=>500}], :filters=>{:age=>[:to_f]}
|
101
100
|
def render(rows, options={})
|
102
101
|
options[:vertical] ? Helpers::VerticalTable.render(rows, options) :
|
103
|
-
|
102
|
+
new(rows, options).render
|
104
103
|
rescue TooManyFieldsForWidthError
|
105
104
|
$stderr.puts "", "** Error: Too many fields for the current width. Configure your width " +
|
106
105
|
"and/or fields to avoid this error. Defaulting to a vertical table. **"
|
@@ -121,6 +120,8 @@ module Hirb
|
|
121
120
|
#:stopdoc:
|
122
121
|
attr_accessor :width, :max_fields, :field_lengths, :fields
|
123
122
|
def initialize(rows, options={})
|
123
|
+
raise ArgumentError, "Table must be an array of hashes or array of arrays" unless rows.is_a?(Array) &&
|
124
|
+
(rows[0].is_a?(Hash) or rows[0].is_a?(Array) or rows.empty?)
|
124
125
|
@options = {:description=>true, :filters=>{}, :change_fields=>{}, :escape_special_chars=>true,
|
125
126
|
:filter_any=>Helpers::Table.filter_any, :resize=>true}.merge(options)
|
126
127
|
@fields = set_fields(rows)
|
@@ -134,19 +135,18 @@ module Hirb
|
|
134
135
|
end
|
135
136
|
|
136
137
|
def set_fields(rows)
|
137
|
-
|
138
|
-
|
138
|
+
@options[:change_fields] = array_to_indices_hash(@options[:change_fields]) if @options[:change_fields].is_a?(Array)
|
139
|
+
return @options[:fields].dup if @options[:fields]
|
140
|
+
|
141
|
+
fields = if rows[0].is_a?(Hash)
|
142
|
+
keys = @options[:all_fields] ? rows.map {|e| e.keys}.flatten.uniq : rows[0].keys
|
143
|
+
keys.sort {|a,b| a.to_s <=> b.to_s}
|
139
144
|
else
|
140
|
-
|
141
|
-
keys = @options[:all_fields] ? rows.map {|e| e.keys}.flatten.uniq : rows[0].keys
|
142
|
-
keys.sort {|a,b| a.to_s <=> b.to_s}
|
143
|
-
else
|
144
|
-
rows[0].is_a?(Array) ? (0..rows[0].length - 1).to_a : []
|
145
|
-
end
|
145
|
+
rows[0].is_a?(Array) ? (0..rows[0].length - 1).to_a : []
|
146
146
|
end
|
147
|
-
|
147
|
+
|
148
148
|
@options[:change_fields].each do |oldf, newf|
|
149
|
-
(index = fields.index(oldf))
|
149
|
+
(index = fields.index(oldf)) && fields[index] = newf
|
150
150
|
end
|
151
151
|
fields
|
152
152
|
end
|
@@ -267,7 +267,8 @@ module Hirb
|
|
267
267
|
|
268
268
|
# find max length for each field; start with the headers
|
269
269
|
def default_field_lengths
|
270
|
-
field_lengths = @headers ? @headers.inject({}) {|h,(k,v)| h[k] = String.size(v); h} :
|
270
|
+
field_lengths = @headers ? @headers.inject({}) {|h,(k,v)| h[k] = String.size(v); h} :
|
271
|
+
@fields.inject({}) {|h,e| h[e] = 1; h }
|
271
272
|
@rows.each do |row|
|
272
273
|
@fields.each do |field|
|
273
274
|
len = String.size(row[field])
|
data/lib/hirb/helpers/tree.rb
CHANGED
@@ -43,6 +43,7 @@ class Hirb::Helpers::Tree
|
|
43
43
|
# [:indent] Number of spaces to indent between levels for basic + number trees. Default is 4.
|
44
44
|
# [:limit] Limits the level or depth of a tree that is displayed. Root node is level 0.
|
45
45
|
# [:description] Displays brief description about tree ie how many nodes it has.
|
46
|
+
# [:multi_line_nodes] Handles multi-lined nodes by indenting their newlines. Default is false.
|
46
47
|
# Examples:
|
47
48
|
# Hirb::Helpers::Tree.render([[0, 'root'], [1, 'child']], :type=>:directory)
|
48
49
|
def render(nodes, options={})
|
@@ -81,28 +82,27 @@ class Hirb::Helpers::Tree
|
|
81
82
|
@indent = ' ' * (@options[:indent] || 4 )
|
82
83
|
@nodes = @nodes.select {|e| e[:level] <= @options[:limit] } if @options[:limit]
|
83
84
|
case @type.to_s
|
84
|
-
when 'directory'
|
85
|
-
|
86
|
-
|
87
|
-
render_number
|
88
|
-
else
|
89
|
-
render_basic
|
85
|
+
when 'directory' then render_directory
|
86
|
+
when 'number' then render_number
|
87
|
+
else render_basic
|
90
88
|
end
|
91
89
|
end
|
92
90
|
|
91
|
+
def render_nodes
|
92
|
+
value_indent = @options[:multi_line_nodes] ? @indent : nil
|
93
|
+
@nodes.map {|e| yield(e) + e.value(value_indent) }.join("\n")
|
94
|
+
end
|
95
|
+
|
93
96
|
def render_directory
|
94
97
|
mark_last_nodes_per_level
|
95
|
-
|
96
|
-
@nodes.each_with_index {|e, i|
|
98
|
+
render_nodes {|e|
|
97
99
|
value = ''
|
98
100
|
unless e.root?
|
99
101
|
value << e.render_parent_characters
|
100
102
|
value << (e[:last_node] ? "`-- " : "|-- ")
|
101
103
|
end
|
102
|
-
value
|
103
|
-
new_nodes << value
|
104
|
+
value
|
104
105
|
}
|
105
|
-
new_nodes.join("\n")
|
106
106
|
end
|
107
107
|
|
108
108
|
def render_number
|
@@ -113,13 +113,13 @@ class Hirb::Helpers::Tree
|
|
113
113
|
counter[parent_level_key] += 1
|
114
114
|
e[:pre_value] = "#{counter[parent_level_key]}. "
|
115
115
|
}
|
116
|
-
|
116
|
+
render_nodes {|e| @indent * e[:level] + e[:pre_value] }
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
def render_basic
|
120
|
-
|
120
|
+
render_nodes {|e| @indent * e[:level] }
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
def validate_nodes
|
124
124
|
@nodes.each do |e|
|
125
125
|
raise ParentlessNodeError if (e[:level] > e.previous[:level]) && (e[:level] - e.previous[:level]) > 1
|
@@ -146,6 +146,10 @@ class Hirb::Helpers::Tree
|
|
146
146
|
replace(hash)
|
147
147
|
end
|
148
148
|
|
149
|
+
def value(indent=nil)
|
150
|
+
indent ? self[:value].gsub("\n", "\n#{indent * self[:level]}") : self[:value]
|
151
|
+
end
|
152
|
+
|
149
153
|
def parent
|
150
154
|
self[:tree].nodes.slice(0 .. self[:index]).reverse.detect {|e| e[:level] < self[:level]}
|
151
155
|
end
|
data/lib/hirb/import_object.rb
CHANGED
data/lib/hirb/menu.rb
CHANGED
@@ -197,7 +197,7 @@ module Hirb
|
|
197
197
|
end
|
198
198
|
|
199
199
|
def table_helper_class?
|
200
|
-
@options[:helper_class].is_a?(Class) &&
|
200
|
+
@options[:helper_class].is_a?(Class) && @options[:helper_class] < Helpers::Table
|
201
201
|
end
|
202
202
|
|
203
203
|
def unalias_field(field)
|
data/lib/hirb/util.rb
CHANGED
data/lib/hirb/version.rb
ADDED
data/lib/hirb/view.rb
CHANGED
@@ -1,6 +1,64 @@
|
|
1
1
|
module Hirb
|
2
|
-
# This class is responsible for managing all view-related functionality.
|
3
|
-
#
|
2
|
+
# This class is responsible for managing all view-related functionality.
|
3
|
+
#
|
4
|
+
# == Create a View
|
5
|
+
# Let's create a simple view for Hash objects:
|
6
|
+
# $ irb -rubygems
|
7
|
+
# >> require 'hirb'
|
8
|
+
# =>true
|
9
|
+
# >> Hirb.enable
|
10
|
+
# =>nil
|
11
|
+
# >> require 'yaml'
|
12
|
+
# =>true
|
13
|
+
#
|
14
|
+
# # A view method is the smallest view
|
15
|
+
# >> def yaml(output); output.to_yaml; end
|
16
|
+
# => nil
|
17
|
+
# # Add the view
|
18
|
+
# >> Hirb.add_view Hash, :method=>:yaml
|
19
|
+
# => true
|
20
|
+
#
|
21
|
+
# # Hashes now appear as yaml
|
22
|
+
# >> {:a=>1, :b=>{:c=>3}}
|
23
|
+
# ---
|
24
|
+
# :a : 1
|
25
|
+
# :b :
|
26
|
+
# :c : 3
|
27
|
+
# => true
|
28
|
+
#
|
29
|
+
# Another way of creating a view is a Helper class:
|
30
|
+
#
|
31
|
+
# # Create yaml view class
|
32
|
+
# >> class Hirb::Helpers::Yaml; def self.render(output, options={}); output.to_yaml; end ;end
|
33
|
+
# =>nil
|
34
|
+
# # Add the view
|
35
|
+
# >> Hirb.add_view Hash, :class=>Hirb::Helpers::Yaml
|
36
|
+
# =>true
|
37
|
+
#
|
38
|
+
# # Hashes appear as yaml like above ...
|
39
|
+
#
|
40
|
+
# == Configure a View
|
41
|
+
# To configure the above Helper class as a view, either pass Hirb.enable a hash:
|
42
|
+
# # In .irbrc
|
43
|
+
# require 'hirb'
|
44
|
+
# # View class needs to come before enable()
|
45
|
+
# class Hirb::Helpers::Yaml; def self.render(output, options={}); output.to_yaml; end ;end
|
46
|
+
# Hirb.enable :output=>{"Hash"=>{:class=>"Hirb::Helpers::Yaml"}}
|
47
|
+
#
|
48
|
+
# Or create a config file at config/hirb.yml or ~/.hirb.yml:
|
49
|
+
# # The config file for the yaml example would look like:
|
50
|
+
# # ---
|
51
|
+
# # :output :
|
52
|
+
# # Hash :
|
53
|
+
# # :class : Hirb::Helpers::Yaml
|
54
|
+
#
|
55
|
+
# # In .irbrc
|
56
|
+
# require 'hirb'
|
57
|
+
# # View class needs to come before enable()
|
58
|
+
# class Hirb::Helpers::Yaml; def self.render(output, options={}); output.to_yaml; end ;end
|
59
|
+
# Hirb.enable
|
60
|
+
#
|
61
|
+
# For more about configuring Hirb, see the Config Files section in Hirb.
|
4
62
|
module View
|
5
63
|
DEFAULT_WIDTH = 120
|
6
64
|
DEFAULT_HEIGHT = 40
|
@@ -10,26 +68,23 @@ module Hirb
|
|
10
68
|
|
11
69
|
# This activates view functionality i.e. the formatter, pager and size detection. If irb exists, it overrides irb's output
|
12
70
|
# method with Hirb::View.view_output. When called multiple times, new configs are merged into the existing config.
|
13
|
-
# If using Wirble, you should call this after it. The view configuration
|
14
|
-
#
|
15
|
-
# In addition to the config keys mentioned in Hirb, the options also take the following keys:
|
71
|
+
# If using Wirble, you should call this after it. The view configuration can be specified in a hash via a config file,
|
72
|
+
# or as options to this method. In addition to the config keys mentioned in Hirb, options also take the following keys:
|
16
73
|
# ==== Options:
|
17
74
|
# * config_file: Name of config file(s) that are merged into existing config
|
18
75
|
# * output_method: Specify an object's class and instance method (separated by a period) to be realiased with
|
19
76
|
# hirb's view system. The instance method should take a string to be output. Default is IRB::Irb.output_value
|
20
77
|
# if using irb.
|
21
78
|
# Examples:
|
22
|
-
# Hirb
|
23
|
-
# Hirb
|
24
|
-
# Hirb::View.enable {|c| c.output = {'String'=>{:class=>'Hirb::Helpers::Table'}} }
|
79
|
+
# Hirb.enable
|
80
|
+
# Hirb.enable :formatter=>false, :output_method=>"Mini.output"
|
25
81
|
def enable(options={}, &block)
|
26
82
|
Array(options.delete(:config_file)).each {|e|
|
27
83
|
@new_config_file = true
|
28
84
|
Hirb.config_files << e
|
29
85
|
}
|
30
86
|
enable_output_method(options.delete(:output_method))
|
31
|
-
|
32
|
-
merge_or_load_config(Util.recursive_hash_merge(options, HashStruct.block_to_hash(block)))
|
87
|
+
merge_or_load_config options
|
33
88
|
resize(config[:width], config[:height])
|
34
89
|
@enabled = true
|
35
90
|
end
|
@@ -102,14 +157,18 @@ module Hirb
|
|
102
157
|
config ? config[:height] : DEFAULT_HEIGHT
|
103
158
|
end
|
104
159
|
|
105
|
-
# Current formatter config
|
160
|
+
# Current formatter config, storing a hash of all static views
|
106
161
|
def formatter_config
|
107
162
|
formatter.config
|
108
163
|
end
|
109
164
|
|
110
|
-
#
|
111
|
-
def
|
112
|
-
|
165
|
+
# Adds a view when View is enabled. See Formatter.add_view for more details.
|
166
|
+
def add(klass, view_config)
|
167
|
+
if enabled?
|
168
|
+
formatter.add_view(klass, view_config)
|
169
|
+
else
|
170
|
+
puts "View must be enabled to add a view"
|
171
|
+
end
|
113
172
|
end
|
114
173
|
|
115
174
|
#:stopdoc:
|
@@ -217,8 +276,4 @@ module Hirb
|
|
217
276
|
#:startdoc:
|
218
277
|
end
|
219
278
|
end
|
220
|
-
|
221
|
-
# Namespace for autoloaded views
|
222
|
-
module Views
|
223
|
-
end
|
224
|
-
end
|
279
|
+
end
|
data/lib/hirb/views.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
module Hirb::Views::CouchDb #:nodoc:
|
2
|
+
def default_couch(obj)
|
3
|
+
{:fields=>([:_id] + obj.class.properties.map {|e| e.name }) }
|
4
|
+
end
|
5
|
+
|
6
|
+
alias_method :couch_rest__extended_document_view, :default_couch
|
7
|
+
alias_method :couch_foo__base_view, :default_couch
|
8
|
+
alias_method :couch_potato__persistence_view, :default_couch
|
9
|
+
end
|
10
|
+
|
11
|
+
Hirb::DynamicView.add Hirb::Views::CouchDb, :helper=>:auto_table
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Hirb::Views::MiscDb #:nodoc:
|
2
|
+
def friendly__document_view(obj)
|
3
|
+
{:fields=>obj.class.attributes.keys - [:id]}
|
4
|
+
end
|
5
|
+
|
6
|
+
def ripple__document_view(obj)
|
7
|
+
{:fields=>obj.class.properties.keys}
|
8
|
+
end
|
9
|
+
|
10
|
+
def d_b_i__row_view(obj)
|
11
|
+
{:fields=>obj.column_names, :table_class=>Hirb::Helpers::Table}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Hirb::DynamicView.add Hirb::Views::MiscDb, :helper=>:auto_table
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Hirb::Views::MongoDb #:nodoc:
|
2
|
+
def mongoid__document_view(obj)
|
3
|
+
{:fields=>['_id'] + obj.class.fields.keys}
|
4
|
+
end
|
5
|
+
|
6
|
+
def mongo_mapper__document_view(obj)
|
7
|
+
{:fields=>obj.class.column_names}
|
8
|
+
end
|
9
|
+
|
10
|
+
def mongo_mapper__embedded_document_view(obj)
|
11
|
+
{:fields=>obj.class.column_names}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Hirb::DynamicView.add Hirb::Views::MongoDb, :helper=>:auto_table
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Hirb::Views::ORM #:nodoc:
|
2
|
+
def data_mapper__resource_view(obj)
|
3
|
+
{:fields=>obj.class.properties.map {|e| e.name }}
|
4
|
+
end
|
5
|
+
|
6
|
+
def sequel__model_view(obj)
|
7
|
+
{:fields=>obj.class.columns}
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Hirb::DynamicView.add Hirb::Views::ORM, :helper=>:auto_table
|