hirber 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|