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