hirber 0.8.0
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/.gemspec +21 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.rdoc +165 -0
- data/CONTRIBUTING.md +1 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +205 -0
- data/Rakefile +35 -0
- data/lib/bond/completions/hirb.rb +15 -0
- data/lib/hirb.rb +84 -0
- data/lib/hirb/console.rb +43 -0
- data/lib/hirb/dynamic_view.rb +113 -0
- data/lib/hirb/formatter.rb +126 -0
- data/lib/hirb/helpers.rb +18 -0
- data/lib/hirb/helpers/auto_table.rb +24 -0
- data/lib/hirb/helpers/markdown_table.rb +14 -0
- data/lib/hirb/helpers/object_table.rb +14 -0
- data/lib/hirb/helpers/parent_child_tree.rb +24 -0
- data/lib/hirb/helpers/tab_table.rb +24 -0
- data/lib/hirb/helpers/table.rb +376 -0
- data/lib/hirb/helpers/table/filters.rb +10 -0
- data/lib/hirb/helpers/table/resizer.rb +82 -0
- data/lib/hirb/helpers/tree.rb +181 -0
- data/lib/hirb/helpers/unicode_table.rb +15 -0
- data/lib/hirb/helpers/vertical_table.rb +37 -0
- data/lib/hirb/import_object.rb +10 -0
- data/lib/hirb/menu.rb +226 -0
- data/lib/hirb/pager.rb +106 -0
- data/lib/hirb/string.rb +44 -0
- data/lib/hirb/util.rb +96 -0
- data/lib/hirb/version.rb +3 -0
- data/lib/hirb/view.rb +272 -0
- 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 +17 -0
- data/lib/hirb/views/orm.rb +11 -0
- data/lib/hirb/views/rails.rb +19 -0
- data/lib/ripl/hirb.rb +15 -0
- data/test/auto_table_test.rb +33 -0
- data/test/console_test.rb +27 -0
- data/test/dynamic_view_test.rb +94 -0
- data/test/formatter_test.rb +176 -0
- data/test/hirb_test.rb +39 -0
- data/test/import_test.rb +9 -0
- data/test/menu_test.rb +272 -0
- data/test/object_table_test.rb +79 -0
- data/test/pager_test.rb +162 -0
- data/test/resizer_test.rb +62 -0
- data/test/table_test.rb +667 -0
- data/test/test_helper.rb +60 -0
- data/test/tree_test.rb +184 -0
- data/test/util_test.rb +59 -0
- data/test/view_test.rb +178 -0
- data/test/views_test.rb +22 -0
- metadata +164 -0
@@ -0,0 +1,15 @@
|
|
1
|
+
complete(:methods=>%w{Hirb::View.enable Hirb.enable}) {
|
2
|
+
%w{config_file output_method output width height formatter pager pager_command}
|
3
|
+
}
|
4
|
+
complete(:methods=>%w{Hirb::Helpers::Table.render table}) {
|
5
|
+
%w{fields headers max_fields max_width resize number change_fields}+
|
6
|
+
%w{filters header_filter filter_any filter_classes vertical all_fields}+
|
7
|
+
%w{description escape_special_chars table_class hide_empty unicode grep_fields}
|
8
|
+
}
|
9
|
+
complete(:method=>"Hirb::Helpers::Tree.render") {
|
10
|
+
%w{type validate indent limit description multi_line_nodes value_method children_method}
|
11
|
+
}
|
12
|
+
complete(:methods=>%w{Hirb::Menu.render menu}) {
|
13
|
+
%w{helper_class prompt ask directions readline two_d default_field action multi_action} +
|
14
|
+
%w{action_object command reopen}
|
15
|
+
}
|
data/lib/hirb.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# Needed by Hirb::String to handle multibyte characters
|
2
|
+
$KCODE = 'u' if RUBY_VERSION < '1.9'
|
3
|
+
|
4
|
+
require 'yaml'
|
5
|
+
require 'hirb/util'
|
6
|
+
require 'hirb/string'
|
7
|
+
require 'hirb/formatter' # must come before helpers/auto_table
|
8
|
+
require 'hirb/dynamic_view'
|
9
|
+
require 'hirb/helpers'
|
10
|
+
require 'hirb/views'
|
11
|
+
require 'hirb/view'
|
12
|
+
require 'hirb/console'
|
13
|
+
require 'hirb/pager'
|
14
|
+
require 'hirb/menu'
|
15
|
+
require 'hirb/version'
|
16
|
+
|
17
|
+
# Most of Hirb's functionality is in Hirb::View.
|
18
|
+
# For a tutorial on configuring and creating views see Hirb::View. For a tutorial on dynamic views see Hirb::DynamicView.
|
19
|
+
#
|
20
|
+
# == Config Files
|
21
|
+
# Hirb can have multiple config files defined by config_files(). These config files
|
22
|
+
# have the following top level keys:
|
23
|
+
# [*:output*] This hash is used by the formatter object. See Hirb::Formatter.config for its format.
|
24
|
+
# [*:width*] Width of the terminal/console. Defaults to Hirb::View::DEFAULT_WIDTH or possibly autodetected when Hirb is enabled.
|
25
|
+
# [*:height*] Height of the terminal/console. Defaults to Hirb::View::DEFAULT_HEIGHT or possibly autodetected when Hirb is enabled.
|
26
|
+
# [*:formatter*] Boolean which determines if the formatter is enabled. Defaults to true.
|
27
|
+
# [*:pager*] Boolean which determines if the pager is enabled. Defaults to true.
|
28
|
+
# [*:pager_command*] Command to be used for paging. Command can have options after it i.e. 'less -r'.
|
29
|
+
# Defaults to common pagers i.e. less and more if detected.
|
30
|
+
# [*:ignore_errors*] Boolean which ignores internal view errors and continues with original view
|
31
|
+
# (i.e. #inspect for irb). Defaults to false.
|
32
|
+
module Hirb
|
33
|
+
class <<self
|
34
|
+
attr_accessor :config_files, :config
|
35
|
+
|
36
|
+
# Enables view functionality. See Hirb::View.enable for details.
|
37
|
+
def enable(options={})
|
38
|
+
View.enable(options)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Disables view functionality. See Hirb::View.disable for details.
|
42
|
+
def disable
|
43
|
+
View.disable
|
44
|
+
end
|
45
|
+
|
46
|
+
# Adds views. See Hirb::View.add for details.
|
47
|
+
def add_view(view, options)
|
48
|
+
View.add(view, options)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Adds views. See Hirb::DynamicView.add for details.
|
52
|
+
def add_dynamic_view(view, options, &block)
|
53
|
+
DynamicView.add(view, options, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Array of config files which are merged sequentially to produce config.
|
57
|
+
# Defaults to config/hirb.yml and ~/.hirb_yml
|
58
|
+
undef :config_files
|
59
|
+
def config_files
|
60
|
+
@config_files ||= default_config_files
|
61
|
+
end
|
62
|
+
|
63
|
+
#:stopdoc:
|
64
|
+
def default_config_files
|
65
|
+
[File.join(Util.find_home, ".hirb.yml")] +
|
66
|
+
(File.exist?('config/hirb.yml') ? ['config/hirb.yml'] : [])
|
67
|
+
end
|
68
|
+
|
69
|
+
def read_config_file(file=config_file)
|
70
|
+
File.exist?(file) ? YAML.load_file(file) : {}
|
71
|
+
end
|
72
|
+
|
73
|
+
undef :config
|
74
|
+
def config(reload=false)
|
75
|
+
if (@config.nil? || reload)
|
76
|
+
@config = config_files.inject({}) {|acc,e|
|
77
|
+
Util.recursive_hash_merge(acc,read_config_file(e))
|
78
|
+
}
|
79
|
+
end
|
80
|
+
@config
|
81
|
+
end
|
82
|
+
#:startdoc:
|
83
|
+
end
|
84
|
+
end
|
data/lib/hirb/console.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Hirb
|
2
|
+
# This module is meant to be extended to provide methods for use in a console/irb shell.
|
3
|
+
# For example:
|
4
|
+
# >> extend Hirb::Console
|
5
|
+
# >> view 'some string', :class=>Some::String::Formatter
|
6
|
+
# >> table [[:row1], [:row2]]
|
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
|
+
|
28
|
+
# Renders a table for the given object. Takes same options as Hirb::Helpers::Table.render.
|
29
|
+
def table(output, options={})
|
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)
|
36
|
+
end
|
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)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module Hirb
|
2
|
+
# This module extends a Helper with the ability to have dynamic views for configured output classes.
|
3
|
+
# After a Helper has extended this module, it can use it within a render() by calling
|
4
|
+
# dynamic_options() to get dynamically generated options for the object it's rendering. See Hirb::Helpers::AutoTable as an example.
|
5
|
+
#
|
6
|
+
# == Dynamic Views
|
7
|
+
# Whereas normal views are generated from helpers with static helper options, dynamic views are generated from helpers and
|
8
|
+
# dynamically generated helper options. Let's look at an example for Rails' ActiveRecord classes:
|
9
|
+
#
|
10
|
+
# Hirb.add_dynamic_view("ActiveRecord::Base", :helper=>:auto_table) {|obj|
|
11
|
+
# {:fields=>obj.class.column_names} }
|
12
|
+
#
|
13
|
+
# From this dynamic view definition, _any_ ActiveRecord model class will render a table with the correct fields, since the fields
|
14
|
+
# are extracted from the output object's class at runtime. Note that dynamic view definitions should return a hash of helper options.
|
15
|
+
#
|
16
|
+
# To define multiple dynamic views, create a Views module where each method ending in '\_view' maps to a class/module:
|
17
|
+
#
|
18
|
+
# module Hirb::Views::ORM
|
19
|
+
# def data_mapper__resource_view(obj)
|
20
|
+
# {:fields=>obj.class.properties.map {|e| e.name }}
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def sequel__model_view(obj)
|
24
|
+
# {:fields=>obj.class.columns}
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# Hirb.add_dynamic_view Hirb::Views::ORM, :helper=>:auto_table
|
29
|
+
#
|
30
|
+
# In this example, 'data_mapper__resource_view' maps to DataMapper::Resource and 'sequel__model_view' maps to Sequel::Model.
|
31
|
+
# Note that when mapping method names to class names, '__' maps to '::' and '_' signals the next letter to be capitalized.
|
32
|
+
module DynamicView
|
33
|
+
# Add dynamic views to output class(es) for a given helper. If defining one view, the first argument is the output class
|
34
|
+
# and a block defines the dynamic view. If defining multiple views, the first argument should be a Views::* module where
|
35
|
+
# each method in the module ending in _view defines a view for an output class. To map output classes to method names in
|
36
|
+
# a Views module, translate'::' to '__' and a capital letter translates to a '_' and a lowercase letter.
|
37
|
+
# ==== Options:
|
38
|
+
# [*:helper*] Required option. Helper class that view(s) use to format. Hirb::Helpers::AutoTable is the only valid
|
39
|
+
# helper among default helpers. Can be given in aliased form i.e. :auto_table -> Hirb::Helpers::AutoTable.
|
40
|
+
#
|
41
|
+
# Examples:
|
42
|
+
# Hirb.add_dynamic_view Hirb::Views::ORM, :helper=>:auto_table
|
43
|
+
# Hirb.add_dynamic_view("ActiveRecord::Base", :helper=>:auto_table) {|obj| {:fields=>obj.class.column_names} }
|
44
|
+
def self.add(view, options, &block)
|
45
|
+
raise ArgumentError, ":helper option is required" unless options[:helper]
|
46
|
+
helper = Helpers.helper_class options[:helper]
|
47
|
+
unless helper.is_a?(Module) && class << helper; self.ancestors; end.include?(self)
|
48
|
+
raise ArgumentError, ":helper option must be a helper that has extended DynamicView"
|
49
|
+
end
|
50
|
+
mod = block ? generate_single_view_module(view, &block) : view
|
51
|
+
raise ArgumentError, "'#{mod}' must be a module" unless mod.is_a?(Module)
|
52
|
+
helper.add_module mod
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.generate_single_view_module(output_mod, &block) #:nodoc:
|
56
|
+
meth = class_to_method output_mod.to_s
|
57
|
+
view_mod = meth.capitalize
|
58
|
+
Views::Single.send(:remove_const, view_mod) if Views::Single.const_defined?(view_mod)
|
59
|
+
mod = Views::Single.const_set(view_mod, Module.new)
|
60
|
+
mod.send(:define_method, meth, block)
|
61
|
+
mod
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.class_to_method(mod) #:nodoc:
|
65
|
+
mod.gsub(/(?!^)([A-Z])/) {|e| '_'+e }.gsub('::_', '__').downcase + '_view'
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns a hash of options based on dynamic views defined for the object's ancestry. If no config is found returns nil.
|
69
|
+
def dynamic_options(obj)
|
70
|
+
view_methods.each do |meth|
|
71
|
+
if obj.class.ancestors.map {|e| e.to_s }.include?(method_to_class(meth))
|
72
|
+
begin
|
73
|
+
return send(meth, obj)
|
74
|
+
rescue
|
75
|
+
raise "View failed to generate for '#{method_to_class(meth)}' "+
|
76
|
+
"while in '#{meth}' with error:\n#{$!.message}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
|
83
|
+
#:stopdoc:
|
84
|
+
def add_module(mod)
|
85
|
+
new_methods = mod.instance_methods.select {|e| e.to_s =~ /_view$/ }.map {|e| e.to_s}
|
86
|
+
return if new_methods.empty?
|
87
|
+
extend mod
|
88
|
+
view_methods.replace(view_methods + new_methods).uniq!
|
89
|
+
update_config(new_methods)
|
90
|
+
end
|
91
|
+
|
92
|
+
def update_config(meths)
|
93
|
+
output_config = meths.inject({}) {|t,e|
|
94
|
+
t[method_to_class(e)] = {:class=>self, :ancestor=>true}; t
|
95
|
+
}
|
96
|
+
Formatter.dynamic_config.merge! output_config
|
97
|
+
end
|
98
|
+
|
99
|
+
def method_to_class(meth)
|
100
|
+
view_method_classes[meth] ||= Util.camelize meth.sub(/_view$/, '').gsub('__', '/')
|
101
|
+
end
|
102
|
+
|
103
|
+
def view_method_classes
|
104
|
+
@view_method_classes ||= {}
|
105
|
+
end
|
106
|
+
#:startdoc:
|
107
|
+
|
108
|
+
# Stores view methods that a Helper has been given via DynamicView.add
|
109
|
+
def view_methods
|
110
|
+
@view_methods ||= []
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Hirb
|
2
|
+
# A Formatter object formats an output object (using Formatter.format_output) into a string based on the views defined
|
3
|
+
# for its class and/or ancestry.
|
4
|
+
class Formatter
|
5
|
+
class<<self
|
6
|
+
# This config is used by Formatter.format_output to lazily load dynamic views defined with Hirb::DynamicView.
|
7
|
+
# This hash has the same format as Formatter.config.
|
8
|
+
attr_accessor :dynamic_config
|
9
|
+
|
10
|
+
# Array of classes whose objects respond to :to_a and allow the first
|
11
|
+
# element of the converted array to determine the output class.
|
12
|
+
attr_accessor :to_a_classes
|
13
|
+
end
|
14
|
+
self.dynamic_config = {}
|
15
|
+
self.to_a_classes = %w{Array Set ActiveRecord::Relation}
|
16
|
+
|
17
|
+
def initialize(additional_config={}) #:nodoc:
|
18
|
+
@klass_config = {}
|
19
|
+
@config = additional_config || {}
|
20
|
+
end
|
21
|
+
|
22
|
+
# A hash of Ruby class strings mapped to view hashes. A view hash must have at least a :method, :output_method
|
23
|
+
# or :class option for a view to be applied to an output. A view hash has the following keys:
|
24
|
+
# [*:method*] Specifies a global (Kernel) method to do the formatting.
|
25
|
+
# [*:class*] Specifies a class to do the formatting, using its render() class method. If a symbol it's converted to a corresponding
|
26
|
+
# Hirb::Helpers::* class if it exists.
|
27
|
+
# [*: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
|
28
|
+
# to every element in the array.
|
29
|
+
# [*:options*] Options to pass the helper method or class.
|
30
|
+
# [*:ancestor*] Boolean which when true causes subclasses of the output class to inherit its config. This doesn't effect the current
|
31
|
+
# output class. Defaults to false. This is used by ActiveRecord classes.
|
32
|
+
#
|
33
|
+
# Examples:
|
34
|
+
# {'WWW::Delicious::Element'=>{:class=>'Hirb::Helpers::ObjectTable', :ancestor=>true, :options=>{:max_width=>180}}}
|
35
|
+
# {'Date'=>{:class=>:auto_table, :ancestor=>true}}
|
36
|
+
# {'Hash'=>{:method=>:puts}}
|
37
|
+
def config
|
38
|
+
@config
|
39
|
+
end
|
40
|
+
|
41
|
+
# Adds the view for the given class and view hash config. See Formatter.config for valid keys for view hash.
|
42
|
+
def add_view(klass, view_config)
|
43
|
+
@klass_config.delete(klass)
|
44
|
+
@config[klass.to_s] = view_config
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
# This method looks for an output object's view in Formatter.config and then Formatter.dynamic_config.
|
49
|
+
# If a view is found, a stringified view is returned based on the object. If no view is found, nil is returned. The options this
|
50
|
+
# class takes are a view hash as described in Formatter.config. These options will be merged with any existing helper
|
51
|
+
# config hash an output class has in Formatter.config. Any block given is passed along to a helper class.
|
52
|
+
def format_output(output, options={}, &block)
|
53
|
+
output_class = determine_output_class(output)
|
54
|
+
options = parse_console_options(options) if options.delete(:console)
|
55
|
+
options = Util.recursive_hash_merge(klass_config(output_class), options)
|
56
|
+
_format_output(output, options, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
#:stopdoc:
|
60
|
+
def to_a_classes
|
61
|
+
@to_a_classes ||= self.class.to_a_classes.map {|e| Util.any_const_get(e) }.compact
|
62
|
+
end
|
63
|
+
|
64
|
+
def _format_output(output, options, &block)
|
65
|
+
output = options[:output_method] ? (output.is_a?(Array) ?
|
66
|
+
output.map {|e| call_output_method(options[:output_method], e) } :
|
67
|
+
call_output_method(options[:output_method], output) ) : output
|
68
|
+
args = [output]
|
69
|
+
args << options[:options] if options[:options] && !options[:options].empty?
|
70
|
+
if options[:method]
|
71
|
+
send(options[:method],*args)
|
72
|
+
elsif options[:class] && (helper_class = Helpers.helper_class(options[:class]))
|
73
|
+
helper_class.render(*args, &block)
|
74
|
+
elsif options[:output_method]
|
75
|
+
output
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def parse_console_options(options) #:nodoc:
|
80
|
+
real_options = [:method, :class, :output_method].inject({}) do |h, e|
|
81
|
+
h[e] = options.delete(e) if options[e]; h
|
82
|
+
end
|
83
|
+
real_options.merge! :options=>options
|
84
|
+
end
|
85
|
+
|
86
|
+
def determine_output_class(output)
|
87
|
+
output.respond_to?(:to_a) && to_a_classes.any? {|e| output.is_a?(e) } ?
|
88
|
+
Array(output)[0].class : output.class
|
89
|
+
end
|
90
|
+
|
91
|
+
def call_output_method(output_method, output)
|
92
|
+
output_method.is_a?(Proc) ? output_method.call(output) : output.send(output_method)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Internal view options built from user-defined ones. Options are built by recursively merging options from oldest
|
96
|
+
# ancestors to the most recent ones.
|
97
|
+
def klass_config(output_class)
|
98
|
+
@klass_config[output_class] ||= build_klass_config(output_class)
|
99
|
+
end
|
100
|
+
|
101
|
+
def build_klass_config(output_class)
|
102
|
+
output_ancestors = output_class.ancestors.map {|e| e.to_s}.reverse
|
103
|
+
output_ancestors.pop
|
104
|
+
hash = output_ancestors.inject({}) {|h, ancestor_klass|
|
105
|
+
add_klass_config_if_true(h, ancestor_klass) {|c, klass| c[klass] && c[klass][:ancestor] }
|
106
|
+
}
|
107
|
+
add_klass_config_if_true(hash, output_class.to_s) {|c, klass| c[klass] }
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_klass_config_if_true(hash, klass)
|
111
|
+
if yield(@config, klass)
|
112
|
+
Util.recursive_hash_merge hash, @config[klass]
|
113
|
+
elsif yield(self.class.dynamic_config, klass)
|
114
|
+
@config[klass] = self.class.dynamic_config[klass].dup # copy to local
|
115
|
+
Util.recursive_hash_merge hash, self.class.dynamic_config[klass]
|
116
|
+
else
|
117
|
+
hash
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def reset_klass_config
|
122
|
+
@klass_config = {}
|
123
|
+
end
|
124
|
+
#:startdoc:
|
125
|
+
end
|
126
|
+
end
|
data/lib/hirb/helpers.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Hirb
|
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
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
%w{table object_table auto_table tree parent_child_tree vertical_table
|
16
|
+
markdown_table unicode_table tab_table}.each do |e|
|
17
|
+
require "hirb/helpers/#{e}"
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
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.
|
16
|
+
def self.render(output, options={})
|
17
|
+
output = Array(output)
|
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)
|
22
|
+
klass.render(output, options)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Creates a markdown table for github
|
2
|
+
class Hirb::Helpers::MarkdownTable < Hirb::Helpers::Table
|
3
|
+
CHARS = {
|
4
|
+
:top => {:left => '', :center => '', :right => '', :horizontal => '',
|
5
|
+
:vertical => {:outside => '|', :inside => ' | '} },
|
6
|
+
:middle => {:left => '|', :center => ' | ', :right => '|', :horizontal => '-'},
|
7
|
+
:bottom => {:left => '', :center => '', :right => '', :horizontal => '',
|
8
|
+
:vertical => {:outside => '|', :inside => ' | '} }
|
9
|
+
}
|
10
|
+
|
11
|
+
def self.render(rows, options={})
|
12
|
+
new(rows, options).render
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Hirb::Helpers::ObjectTable < Hirb::Helpers::Table
|
2
|
+
# Rows are any ruby objects. Takes same options as Hirb::Helpers::Table.render except as noted below.
|
3
|
+
#
|
4
|
+
# ==== Options:
|
5
|
+
# [:fields] Methods of the object to represent as columns. Defaults to [:to_s].
|
6
|
+
def self.render(rows, options ={})
|
7
|
+
options[:fields] ||= [:to_s]
|
8
|
+
options[:headers] ||= {:to_s=>'value'} if options[:fields] == [:to_s]
|
9
|
+
item_hashes = options[:fields].empty? ? [] : Array(rows).inject([]) {|t,item|
|
10
|
+
t << options[:fields].inject({}) {|h,f| h[f] = item.__send__(f); h}
|
11
|
+
}
|
12
|
+
super(item_hashes, options)
|
13
|
+
end
|
14
|
+
end
|