Chrononaut-hirb 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +19 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +164 -0
- data/Rakefile +50 -0
- data/VERSION.yml +4 -0
- data/lib/hirb.rb +56 -0
- data/lib/hirb/console.rb +43 -0
- data/lib/hirb/formatter.rb +199 -0
- data/lib/hirb/hash_struct.rb +17 -0
- data/lib/hirb/helpers.rb +7 -0
- data/lib/hirb/helpers/active_record_table.rb +16 -0
- data/lib/hirb/helpers/auto_table.rb +15 -0
- data/lib/hirb/helpers/object_table.rb +15 -0
- data/lib/hirb/helpers/parent_child_tree.rb +22 -0
- data/lib/hirb/helpers/table.rb +243 -0
- data/lib/hirb/helpers/tree.rb +177 -0
- data/lib/hirb/import_object.rb +10 -0
- data/lib/hirb/menu.rb +47 -0
- data/lib/hirb/pager.rb +94 -0
- data/lib/hirb/util.rb +80 -0
- data/lib/hirb/view.rb +177 -0
- data/lib/hirb/views/activerecord_base.rb +9 -0
- data/test/console_test.rb +12 -0
- data/test/formatter_test.rb +172 -0
- data/test/hirb_test.rb +23 -0
- data/test/import_test.rb +9 -0
- data/test/menu_test.rb +94 -0
- data/test/pager_test.rb +164 -0
- data/test/table_test.rb +374 -0
- data/test/test_helper.rb +47 -0
- data/test/tree_test.rb +167 -0
- data/test/util_test.rb +56 -0
- data/test/view_test.rb +116 -0
- metadata +96 -0
data/lib/hirb/menu.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
module Hirb
|
2
|
+
# This class provides a selection menu using Hirb's table helpers by default to display choices.
|
3
|
+
class Menu
|
4
|
+
# Menu which asks to select from the given array and returns the selected menu items as an array. See Hirb::Util.choose_from_array
|
5
|
+
# for the syntax for specifying selections. All options except for the ones below are passed to render the menu.
|
6
|
+
#
|
7
|
+
# ==== Options:
|
8
|
+
# [:helper_class] Helper class to render menu. Helper class is expected to implement numbering given a :number option.
|
9
|
+
# To use a very basic menu, set this to false. Defaults to Hirb::Helpers::AutoTable.
|
10
|
+
# [:prompt] String for menu prompt. Defaults to "Choose: ".
|
11
|
+
# [:validate_one] Validates that only one item in array is chosen and returns just that item. Default is false.
|
12
|
+
# [:ask] Always ask for input, even if there is only one choice. Default is true.
|
13
|
+
# Examples:
|
14
|
+
# extend Hirb::Console
|
15
|
+
# menu([1,2,3], :fields=>[:field1, :field2], :validate_one=>true)
|
16
|
+
# menu([1,2,3], :helper_class=>Hirb::Helpers::Table)
|
17
|
+
def self.render(output, options={})
|
18
|
+
default_options = {:helper_class=>Hirb::Helpers::AutoTable, :prompt=>"Choose #{options[:validate_one] ? 'one' : ''}: ", :ask=>true}
|
19
|
+
options = default_options.merge(options)
|
20
|
+
output = [output] unless output.is_a?(Array)
|
21
|
+
chosen = choose_from_menu(output, options)
|
22
|
+
yield(chosen) if block_given? && chosen.is_a?(Array) && chosen.size > 0
|
23
|
+
chosen
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.choose_from_menu(output, options) #:nodoc:
|
27
|
+
return output if output.size == 1 && !options[:ask]
|
28
|
+
if (helper_class = Util.any_const_get(options[:helper_class]))
|
29
|
+
View.render_output(output, :class=>options[:helper_class], :options=>options.merge(:number=>true))
|
30
|
+
else
|
31
|
+
output.each_with_index {|e,i| puts "#{i+1}: #{e}" }
|
32
|
+
end
|
33
|
+
print options[:prompt]
|
34
|
+
input = $stdin.gets.chomp.strip
|
35
|
+
chosen = Util.choose_from_array(output, input)
|
36
|
+
if options[:validate_one]
|
37
|
+
if chosen.size != 1
|
38
|
+
$stderr.puts "Choose one. You chose #{chosen.size} items."
|
39
|
+
return nil
|
40
|
+
else
|
41
|
+
return chosen[0]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
chosen
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/hirb/pager.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
module Hirb
|
2
|
+
# This class provides class methods for paging and an object which can conditionally page given a terminal size that is exceeded.
|
3
|
+
class Pager
|
4
|
+
class<<self
|
5
|
+
# Pages using a configured or detected shell command.
|
6
|
+
def command_pager(output, options={})
|
7
|
+
basic_pager(output) if valid_pager_command?(options[:pager_command])
|
8
|
+
end
|
9
|
+
|
10
|
+
def pager_command(*commands) #:nodoc:
|
11
|
+
@pager_command = (!@pager_command.nil? && commands.empty?) ? @pager_command :
|
12
|
+
begin
|
13
|
+
commands = [ENV['PAGER'], 'less', 'more', 'pager'] if commands.empty?
|
14
|
+
commands.compact.uniq.find {|e| Util.command_exists?(e[/\w+/]) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Pages with a ruby-only pager which either pages or quits.
|
19
|
+
def default_pager(output, options={})
|
20
|
+
pager = new(options[:width], options[:height])
|
21
|
+
while pager.activated_by?(output, options[:inspect])
|
22
|
+
puts pager.slice!(output, options[:inspect])
|
23
|
+
return unless continue_paging?
|
24
|
+
end
|
25
|
+
puts output
|
26
|
+
puts "=== Pager finished. ==="
|
27
|
+
end
|
28
|
+
|
29
|
+
#:stopdoc:
|
30
|
+
def valid_pager_command?(cmd)
|
31
|
+
cmd ? pager_command(cmd) : pager_command
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def basic_pager(output)
|
36
|
+
pager = IO.popen(pager_command, "w")
|
37
|
+
begin
|
38
|
+
save_stdout = STDOUT.clone
|
39
|
+
STDOUT.reopen(pager)
|
40
|
+
STDOUT.puts output
|
41
|
+
ensure
|
42
|
+
STDOUT.reopen(save_stdout)
|
43
|
+
save_stdout.close
|
44
|
+
pager.close
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def continue_paging?
|
49
|
+
puts "=== Press enter/return to continue or q to quit: ==="
|
50
|
+
!$stdin.gets.chomp[/q/i]
|
51
|
+
end
|
52
|
+
#:startdoc:
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_reader :width, :height
|
56
|
+
|
57
|
+
def initialize(width, height, options={})
|
58
|
+
resize(width, height)
|
59
|
+
@pager_command = options[:pager_command] if options[:pager_command]
|
60
|
+
end
|
61
|
+
|
62
|
+
# Pages given string using configured pager.
|
63
|
+
def page(string, inspect_mode)
|
64
|
+
if self.class.valid_pager_command?(@pager_command)
|
65
|
+
self.class.command_pager(string, :pager_command=>@pager_command)
|
66
|
+
else
|
67
|
+
self.class.default_pager(string, :width=>@width, :height=>@height, :inspect=>inspect_mode)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def slice!(output, inspect_mode=false) #:nodoc:
|
72
|
+
effective_height = @height - 2 # takes into account pager prompt
|
73
|
+
if inspect_mode
|
74
|
+
sliced_output = output.slice(0, @width * effective_height)
|
75
|
+
output.replace output.slice(@width * effective_height..-1)
|
76
|
+
sliced_output
|
77
|
+
else
|
78
|
+
# could use output.scan(/[^\n]*\n?/) instead of split
|
79
|
+
sliced_output = output.split("\n").slice(0, effective_height).join("\n")
|
80
|
+
output.replace output.split("\n").slice(effective_height..-1).join("\n")
|
81
|
+
sliced_output
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Determines if string should be paged based on configured width and height.
|
86
|
+
def activated_by?(string_to_page, inspect_mode=false)
|
87
|
+
inspect_mode ? (string_to_page.size > @height * @width) : (string_to_page.count("\n") > @height)
|
88
|
+
end
|
89
|
+
|
90
|
+
def resize(width, height) #:nodoc:
|
91
|
+
@width, @height = Hirb::View.determine_terminal_size(width, height)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/lib/hirb/util.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Hirb
|
2
|
+
# Group of handy utility functions used throughout Hirb.
|
3
|
+
module Util
|
4
|
+
extend self
|
5
|
+
# Returns a constant like Module#const_get no matter what namespace it's nested in.
|
6
|
+
# Returns nil if the constant is not found.
|
7
|
+
def any_const_get(name)
|
8
|
+
return name if name.is_a?(Module)
|
9
|
+
begin
|
10
|
+
klass = Object
|
11
|
+
name.split('::').each {|e|
|
12
|
+
klass = klass.const_get(e)
|
13
|
+
}
|
14
|
+
klass
|
15
|
+
rescue
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Recursively merge hash1 with hash2.
|
21
|
+
def recursive_hash_merge(hash1, hash2)
|
22
|
+
hash1.merge(hash2) {|k,o,n| (o.is_a?(Hash)) ? recursive_hash_merge(o,n) : n}
|
23
|
+
end
|
24
|
+
|
25
|
+
# From Rails ActiveSupport, converting undescored lowercase to camel uppercase.
|
26
|
+
def camelize(string)
|
27
|
+
string.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
28
|
+
end
|
29
|
+
|
30
|
+
# Used by Hirb::Menu to select items from an array. Array counting starts at 1. Ranges of numbers are specified with a '-' or '..'.
|
31
|
+
# Multiple ranges can be comma delimited. Anything that isn't a valid number is ignored. All elements can be returned with a '*'.
|
32
|
+
# Examples:
|
33
|
+
# 1-3,5-6 -> [1,2,3,5,6]
|
34
|
+
# * -> all elements in array
|
35
|
+
# '' -> []
|
36
|
+
def choose_from_array(array, input, options={})
|
37
|
+
options = {:splitter=>","}.merge(options)
|
38
|
+
return array if input.strip == '*'
|
39
|
+
result = []
|
40
|
+
input.split(options[:splitter]).each do |e|
|
41
|
+
if e =~ /-|\.\./
|
42
|
+
min,max = e.split(/-|\.\./)
|
43
|
+
slice_min = min.to_i - 1
|
44
|
+
result.push(*array.slice(slice_min, max.to_i - min.to_i + 1))
|
45
|
+
elsif e =~ /\s*(\d+)\s*/
|
46
|
+
index = $1.to_i - 1
|
47
|
+
next if index < 0
|
48
|
+
result.push(array[index]) if array[index]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
return result
|
52
|
+
end
|
53
|
+
|
54
|
+
# Determines if a shell command exists by searching for it in ENV['PATH'].
|
55
|
+
def command_exists?(command)
|
56
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).any? {|d| File.exists? File.join(d, command) }
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns [width, height] of terminal when detected, nil if not detected.
|
60
|
+
# Think of this as a simpler version of Highline's Highline::SystemExtensions.terminal_size()
|
61
|
+
def detect_terminal_size
|
62
|
+
(ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/) ? [ENV['COLUMNS'].to_i, ENV['LINES'].to_i] :
|
63
|
+
( command_exists?('stty') ? `stty size`.scan(/\d+/).map { |s| s.to_i }.reverse : nil )
|
64
|
+
rescue
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
|
68
|
+
# Captures STDOUT of anything run in its block and returns it as string.
|
69
|
+
def capture_stdout(&block)
|
70
|
+
original_stdout = $stdout
|
71
|
+
$stdout = fake = StringIO.new
|
72
|
+
begin
|
73
|
+
yield
|
74
|
+
ensure
|
75
|
+
$stdout = original_stdout
|
76
|
+
end
|
77
|
+
fake.string
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/hirb/view.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
module Hirb
|
2
|
+
# This class is responsible for managing all view-related functionality. Its functionality is determined by setting up a configuration file
|
3
|
+
# as explained in Hirb and/or passed configuration directly to Hirb.enable. Most of the functionality in this class is dormant until enabled.
|
4
|
+
module View
|
5
|
+
DEFAULT_WIDTH = 120
|
6
|
+
DEFAULT_HEIGHT = 40
|
7
|
+
class << self
|
8
|
+
attr_accessor :render_method
|
9
|
+
attr_reader :config
|
10
|
+
|
11
|
+
# This activates view functionality i.e. the formatter, pager and size detection. If irb exists, it overrides irb's output
|
12
|
+
# method with Hirb::View.view_output. If using Wirble, you should call this after it. The view configuration
|
13
|
+
# can be specified in a hash via a config file, as options to this method, as this method's block or any combination of these three.
|
14
|
+
# In addition to the config keys mentioned in Hirb, the options also take the following keys:
|
15
|
+
# Options:
|
16
|
+
# * config_file: Name of config file to read.
|
17
|
+
# Examples:
|
18
|
+
# Hirb::View.enable
|
19
|
+
# Hirb::View.enable :formatter=>false
|
20
|
+
# Hirb::View.enable {|c| c.output = {'String'=>{:class=>'Hirb::Helpers::Table'}} }
|
21
|
+
def enable(options={}, &block)
|
22
|
+
return puts("Already enabled.") if @enabled
|
23
|
+
@enabled = true
|
24
|
+
Hirb.config_file = options.delete(:config_file) if options[:config_file]
|
25
|
+
load_config(Util.recursive_hash_merge(options, HashStruct.block_to_hash(block)))
|
26
|
+
resize(config[:width], config[:height])
|
27
|
+
if Object.const_defined?(:IRB)
|
28
|
+
::IRB::Irb.class_eval do
|
29
|
+
alias :non_hirb_view_output :output_value
|
30
|
+
def output_value #:nodoc:
|
31
|
+
Hirb::View.view_output(@context.last_value) || Hirb::View.page_output(@context.last_value.inspect, true) ||
|
32
|
+
non_hirb_view_output
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Indicates if Hirb::View is enabled.
|
39
|
+
def enabled?
|
40
|
+
@enabled || false
|
41
|
+
end
|
42
|
+
|
43
|
+
# Disable's Hirb's output and revert's irb's output method if irb exists.
|
44
|
+
def disable
|
45
|
+
@enabled = false
|
46
|
+
if Object.const_defined?(:IRB)
|
47
|
+
::IRB::Irb.class_eval do
|
48
|
+
alias :output_value :non_hirb_view_output
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Toggles pager on or off. The pager only works while Hirb::View is enabled.
|
54
|
+
def toggle_pager
|
55
|
+
config[:pager] = !config[:pager]
|
56
|
+
end
|
57
|
+
|
58
|
+
# Toggles formatter on or off.
|
59
|
+
def toggle_formatter
|
60
|
+
config[:formatter] = !config[:formatter]
|
61
|
+
end
|
62
|
+
|
63
|
+
# Resizes the console width and height for use with the table and pager i.e. after having resized the console window. *nix users
|
64
|
+
# should only have to call this method. Non-*nix users should call this method with explicit width and height. If you don't know
|
65
|
+
# your width and height, in irb play with "a"* width to find width and puts "a\n" * height to find height.
|
66
|
+
def resize(width=nil, height=nil)
|
67
|
+
config[:width], config[:height] = determine_terminal_size(width, height)
|
68
|
+
pager.resize(config[:width], config[:height])
|
69
|
+
end
|
70
|
+
|
71
|
+
# This is the main method of this class. When view is enabled, this method searches for a formatter it can use for the output and if
|
72
|
+
# successful renders it using render_method(). The options this method takes are helper config hashes as described in
|
73
|
+
# Hirb::Formatter.format_output(). Returns true if successful and false if no formatting is done or if not enabled.
|
74
|
+
def view_output(output, options={})
|
75
|
+
enabled? && config[:formatter] && render_output(output, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Captures STDOUT and renders it using render_method(). The main use case is to conditionally page captured stdout.
|
79
|
+
def capture_and_render(&block)
|
80
|
+
render_method.call Util.capture_stdout(&block)
|
81
|
+
end
|
82
|
+
|
83
|
+
# A lambda or proc which handles the final formatted object.
|
84
|
+
# Although this pages/puts the object by default, it could be set to do other things
|
85
|
+
# i.e. write the formatted object to a file.
|
86
|
+
def render_method
|
87
|
+
@render_method ||= default_render_method
|
88
|
+
end
|
89
|
+
|
90
|
+
# Resets render_method back to its default.
|
91
|
+
def reset_render_method
|
92
|
+
@render_method = default_render_method
|
93
|
+
end
|
94
|
+
|
95
|
+
# Current console width
|
96
|
+
def width
|
97
|
+
config ? config[:width] : DEFAULT_WIDTH
|
98
|
+
end
|
99
|
+
|
100
|
+
# Current console height
|
101
|
+
def height
|
102
|
+
config ? config[:height] : DEFAULT_HEIGHT
|
103
|
+
end
|
104
|
+
|
105
|
+
# Current formatter config
|
106
|
+
def formatter_config
|
107
|
+
formatter.config
|
108
|
+
end
|
109
|
+
|
110
|
+
# Sets the helper config for the given output class.
|
111
|
+
def format_class(klass, helper_config)
|
112
|
+
formatter.format_class(klass, helper_config)
|
113
|
+
end
|
114
|
+
|
115
|
+
#:stopdoc:
|
116
|
+
def render_output(output, options={})
|
117
|
+
if (formatted_output = formatter.format_output(output, options))
|
118
|
+
render_method.call(formatted_output)
|
119
|
+
true
|
120
|
+
else
|
121
|
+
false
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def determine_terminal_size(width, height)
|
126
|
+
detected = (width.nil? || height.nil?) ? Util.detect_terminal_size || [] : []
|
127
|
+
[width || detected[0] || DEFAULT_WIDTH , height || detected[1] || DEFAULT_HEIGHT]
|
128
|
+
end
|
129
|
+
|
130
|
+
def page_output(output, inspect_mode=false)
|
131
|
+
if enabled? && config[:pager] && pager.activated_by?(output, inspect_mode)
|
132
|
+
pager.page(output, inspect_mode)
|
133
|
+
true
|
134
|
+
else
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def pager
|
140
|
+
@pager ||= Pager.new(config[:width], config[:height], :pager_command=>config[:pager_command])
|
141
|
+
end
|
142
|
+
|
143
|
+
def pager=(value); @pager = value; end
|
144
|
+
|
145
|
+
def formatter(reload=false)
|
146
|
+
@formatter = reload || @formatter.nil? ? Formatter.new(config[:output]) : @formatter
|
147
|
+
end
|
148
|
+
|
149
|
+
def formatter=(value); @formatter = value; end
|
150
|
+
|
151
|
+
def load_config(additional_config={})
|
152
|
+
@config = Util.recursive_hash_merge default_config, additional_config
|
153
|
+
formatter(true)
|
154
|
+
true
|
155
|
+
end
|
156
|
+
|
157
|
+
def config_loaded?; !!@config; end
|
158
|
+
|
159
|
+
def config
|
160
|
+
@config
|
161
|
+
end
|
162
|
+
|
163
|
+
def default_render_method
|
164
|
+
lambda {|output| page_output(output) || puts(output) }
|
165
|
+
end
|
166
|
+
|
167
|
+
def default_config
|
168
|
+
Util.recursive_hash_merge({:pager=>true, :formatter=>true}, Hirb.config || {})
|
169
|
+
end
|
170
|
+
#:startdoc:
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Namespace for autoloaded views
|
175
|
+
module Views
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
class Hirb::ConsoleTest < Test::Unit::TestCase
|
4
|
+
context "parse_input" do
|
5
|
+
test "config is set if it wasn't before" do
|
6
|
+
reset_config
|
7
|
+
Hirb::View.expects(:render_output)
|
8
|
+
Hirb::Console.render_output('blah')
|
9
|
+
Hirb::View.config.is_a?(Hash).should == true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper')
|
2
|
+
|
3
|
+
module Hirb
|
4
|
+
class FormatterTest < Test::Unit::TestCase
|
5
|
+
context "formatter" do
|
6
|
+
def set_formatter(hash={})
|
7
|
+
@formatter = Formatter.new(hash)
|
8
|
+
end
|
9
|
+
|
10
|
+
before(:all) { eval "module ::Dooda; end" }
|
11
|
+
|
12
|
+
test "klass_config merges ancestor options" do
|
13
|
+
set_formatter "String"=>{:args=>[1,2]}, "Object"=>{:method=>:object_output, :ancestor=>true}, "Kernel"=>{:method=>:default_output}
|
14
|
+
expected_result = {:method=>:object_output, :args=>[1, 2], :ancestor=>true}
|
15
|
+
@formatter.klass_config(String).should == expected_result
|
16
|
+
end
|
17
|
+
|
18
|
+
test "klass_config doesn't merge ancestor options" do
|
19
|
+
set_formatter "String"=>{:args=>[1,2]}, "Object"=>{:method=>:object_output}, "Kernel"=>{:method=>:default_output}
|
20
|
+
expected_result = {:args=>[1, 2]}
|
21
|
+
@formatter.klass_config(String).should == expected_result
|
22
|
+
end
|
23
|
+
|
24
|
+
test "klass_config returns hash when nothing found" do
|
25
|
+
set_formatter.klass_config(String).should == {}
|
26
|
+
end
|
27
|
+
|
28
|
+
test "reload detects new Hirb::Views" do
|
29
|
+
set_formatter
|
30
|
+
@formatter.config.keys.include?('Zzz').should be(false)
|
31
|
+
eval "module ::Hirb::Views::Zzz; def self.render; end; end"
|
32
|
+
@formatter.reload
|
33
|
+
@formatter.config.keys.include?('Zzz').should be(true)
|
34
|
+
end
|
35
|
+
|
36
|
+
test "format_class sets formatter config" do
|
37
|
+
set_formatter
|
38
|
+
@formatter.format_class ::Dooda, :class=>"DoodaView"
|
39
|
+
@formatter.klass_config(::Dooda).should == {:class=>"DoodaView"}
|
40
|
+
end
|
41
|
+
|
42
|
+
test "format_class overwrites existing formatter config" do
|
43
|
+
set_formatter "Dooda"=>{:class=>"DoodaView"}
|
44
|
+
@formatter.format_class ::Dooda, :class=>"DoodaView2"
|
45
|
+
@formatter.klass_config(::Dooda).should == {:class=>"DoodaView2"}
|
46
|
+
end
|
47
|
+
|
48
|
+
test "parse_console_options passes all options except for formatter options into :options" do
|
49
|
+
set_formatter
|
50
|
+
options = {:class=>'blah', :method=>'blah', :output_method=>'blah', :blah=>'blah'}
|
51
|
+
expected_options = {:class=>'blah', :method=>'blah', :output_method=>'blah', :options=>{:blah=>'blah'}}
|
52
|
+
@formatter.parse_console_options(options).should == expected_options
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "enable" do
|
57
|
+
before(:each) { View.formatter = nil; reset_config }
|
58
|
+
after(:each) { Hirb.disable }
|
59
|
+
|
60
|
+
def formatter_config
|
61
|
+
View.formatter.config
|
62
|
+
end
|
63
|
+
|
64
|
+
test "sets default formatter config" do
|
65
|
+
eval "module ::Hirb::Views::Something_Base; def self.render; end; end"
|
66
|
+
Hirb.enable
|
67
|
+
formatter_config["Something::Base"].should == {:class=>"Hirb::Views::Something_Base"}
|
68
|
+
end
|
69
|
+
|
70
|
+
test "sets default formatter config with default_options" do
|
71
|
+
eval "module ::Hirb::Views::Blah; def self.render; end; def self.default_options; {:ancestor=>true}; end; end"
|
72
|
+
Hirb.enable
|
73
|
+
formatter_config["Blah"].should == {:class=>"Hirb::Views::Blah", :ancestor=>true}
|
74
|
+
end
|
75
|
+
|
76
|
+
test "with block sets formatter config" do
|
77
|
+
class_hash = {"Something::Base"=>{:class=>"BlahBlah"}}
|
78
|
+
Hirb.enable {|c| c.output = class_hash }
|
79
|
+
formatter_config['Something::Base'].should == class_hash['Something::Base']
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "format_output" do
|
84
|
+
def view_output(*args, &block); View.view_output(*args, &block); end
|
85
|
+
def render_method(*args); View.render_method(*args); end
|
86
|
+
|
87
|
+
def enable_with_output(value)
|
88
|
+
Hirb.enable :output=>value
|
89
|
+
end
|
90
|
+
|
91
|
+
before(:all) {
|
92
|
+
eval %[module ::Commify
|
93
|
+
def self.render(strings)
|
94
|
+
strings = [strings] unless strings.is_a?(Array)
|
95
|
+
strings.map {|e| e.split('').join(',')}.join("\n")
|
96
|
+
end
|
97
|
+
end]
|
98
|
+
reset_config
|
99
|
+
}
|
100
|
+
before(:each) { View.formatter = nil; reset_config }
|
101
|
+
after(:each) { Hirb.disable }
|
102
|
+
|
103
|
+
test "formats with method option" do
|
104
|
+
eval "module ::Kernel; def commify(string); string.split('').join(','); end; end"
|
105
|
+
enable_with_output "String"=>{:method=>:commify}
|
106
|
+
render_method.expects(:call).with('d,u,d,e')
|
107
|
+
view_output('dude')
|
108
|
+
end
|
109
|
+
|
110
|
+
test "formats with class option" do
|
111
|
+
enable_with_output "String"=>{:class=>"Commify"}
|
112
|
+
render_method.expects(:call).with('d,u,d,e')
|
113
|
+
view_output('dude')
|
114
|
+
end
|
115
|
+
|
116
|
+
test "formats with class option as symbol" do
|
117
|
+
enable_with_output "String"=>{:class=>:auto_table}
|
118
|
+
Helpers::AutoTable.expects(:render)
|
119
|
+
view_output('dude')
|
120
|
+
end
|
121
|
+
|
122
|
+
test "formats output array" do
|
123
|
+
enable_with_output "String"=>{:class=>"Commify"}
|
124
|
+
render_method.expects(:call).with('d,u,d,e')
|
125
|
+
view_output(['dude'])
|
126
|
+
end
|
127
|
+
|
128
|
+
test "formats with options option" do
|
129
|
+
eval "module ::Blahify; def self.render(*args); end; end"
|
130
|
+
enable_with_output "String"=>{:class=>"Blahify", :options=>{:fields=>%w{a b}}}
|
131
|
+
Blahify.expects(:render).with('dude', :fields=>%w{a b})
|
132
|
+
view_output('dude')
|
133
|
+
end
|
134
|
+
|
135
|
+
test "doesn't format and returns false when no format method found" do
|
136
|
+
Hirb.enable
|
137
|
+
render_method.expects(:call).never
|
138
|
+
view_output(Date.today).should == false
|
139
|
+
end
|
140
|
+
|
141
|
+
test "formats with output_method option as method" do
|
142
|
+
enable_with_output 'String'=>{:class=>"Commify", :output_method=>:chop}
|
143
|
+
render_method.expects(:call).with('d,u,d')
|
144
|
+
view_output('dude')
|
145
|
+
end
|
146
|
+
|
147
|
+
test "formats with output_method option as proc" do
|
148
|
+
enable_with_output 'String'=>{:class=>"Commify", :output_method=>lambda {|e| e.chop}}
|
149
|
+
render_method.expects(:call).with('d,u,d')
|
150
|
+
view_output('dude')
|
151
|
+
end
|
152
|
+
|
153
|
+
test "formats output array with output_method option" do
|
154
|
+
enable_with_output 'String'=>{:class=>"Commify", :output_method=>:chop}
|
155
|
+
render_method.expects(:call).with("d,u,d\nm,a")
|
156
|
+
view_output(['dude', 'man'])
|
157
|
+
end
|
158
|
+
|
159
|
+
test "formats with explicit class option" do
|
160
|
+
enable_with_output 'String'=>{:class=>"Blahify"}
|
161
|
+
render_method.expects(:call).with('d,u,d,e')
|
162
|
+
view_output('dude', :class=>"Commify")
|
163
|
+
end
|
164
|
+
|
165
|
+
test "formats with explicit options option merges with existing options" do
|
166
|
+
enable_with_output "String"=>{:class=>"Commify", :options=>{:fields=>%w{f1 f2}}}
|
167
|
+
Commify.expects(:render).with('dude', :max_width=>10, :fields=>%w{f1 f2})
|
168
|
+
view_output('dude', :options=>{:max_width=>10})
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|