wrong 0.6.3-java → 0.7.0-java
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +10 -7
- data/lib/wrong.rb +1 -0
- data/lib/wrong/adapters/rspec.rb +4 -0
- data/lib/wrong/assert.rb +1 -2
- data/lib/wrong/chunk.rb +5 -170
- data/lib/wrong/close_to.rb +7 -1
- data/lib/wrong/config.rb +3 -3
- data/lib/wrong/d.rb +2 -1
- data/lib/wrong/failure_message.rb +109 -7
- data/lib/wrong/message/string_comparison.rb +1 -1
- data/lib/wrong/sexp_ext.rb +2 -1
- data/lib/wrong/terminal.rb +43 -0
- data/lib/wrong/version.rb +1 -1
- data/test/adapters/railsapp/app/controllers/application_controller.rb +3 -0
- data/test/adapters/railsapp/app/helpers/application_helper.rb +2 -0
- data/test/adapters/railsapp/config/application.rb +54 -0
- data/test/adapters/railsapp/config/boot.rb +6 -0
- data/test/adapters/railsapp/config/environment.rb +5 -0
- data/test/adapters/railsapp/config/environments/development.rb +30 -0
- data/test/adapters/railsapp/config/environments/production.rb +60 -0
- data/test/adapters/railsapp/config/environments/test.rb +42 -0
- data/test/adapters/railsapp/config/initializers/backtrace_silencers.rb +7 -0
- data/test/adapters/railsapp/config/initializers/inflections.rb +10 -0
- data/test/adapters/railsapp/config/initializers/mime_types.rb +5 -0
- data/test/adapters/railsapp/config/initializers/secret_token.rb +7 -0
- data/test/adapters/railsapp/config/initializers/session_store.rb +8 -0
- data/test/adapters/railsapp/config/initializers/wrap_parameters.rb +14 -0
- data/test/adapters/railsapp/config/routes.rb +58 -0
- data/test/adapters/railsapp/db/seeds.rb +7 -0
- data/test/adapters/railsapp/spec/spec_helper.rb +33 -0
- data/test/adapters/railsapp/spec/wrong_spec.rb +8 -0
- data/test/adapters/rspec_rails_test.rb +4 -4
- data/test/adapters/rspec_test.rb +2 -2
- data/test/assert_advanced_test.rb +9 -1
- data/test/chunk_test.rb +0 -200
- data/test/close_to_test.rb +34 -2
- data/test/d_test.rb +2 -2
- data/test/eventually_test.rb +27 -34
- data/test/failure_message_test.rb +212 -13
- data/test/test_helper.rb +2 -2
- metadata +47 -8
- data/lib/wrong/ruby2ruby_patch.rb +0 -37
data/README.markdown
CHANGED
@@ -100,6 +100,8 @@ If you want to compare floats, try this:
|
|
100
100
|
|
101
101
|
If you don't want `close_to?` cluttering up `Float` in your test runs then use `include Wrong::Assert` instead of `include Wrong`.
|
102
102
|
|
103
|
+
`close_to?` also works on `Time`s, `Date`s, and `DateTime`s. (The default tolerance of 1 msec may be too small for you.)
|
104
|
+
|
103
105
|
### d
|
104
106
|
|
105
107
|
We also implement the most amazing debugging method ever, `d`, which gives you a sort of mini-wrong wherever you want it
|
@@ -251,29 +253,30 @@ Wrong is compatible with RSpec and MiniTest::Spec, and probably Cucumber too, so
|
|
251
253
|
Here's an RSpec example:
|
252
254
|
|
253
255
|
require "wrong/adapters/rspec"
|
254
|
-
Wrong.config.alias_assert :
|
256
|
+
Wrong.config.alias_assert :expect, override: true
|
255
257
|
|
256
258
|
describe BleuCheese do
|
257
259
|
it "stinks" do
|
258
|
-
|
260
|
+
cheese = BleuCheese.new
|
261
|
+
expect { cheese.smell > 9000 }
|
259
262
|
end
|
260
263
|
end
|
261
264
|
|
262
265
|
This makes your code read like a BDD-style DSL, without RSpec's "should" syntax (which is, let's face it, pretty weird the first few hundred times you have to use it). Compare
|
263
266
|
|
264
|
-
|
267
|
+
expect { cheese.smell > 9000 }
|
265
268
|
|
266
269
|
to
|
267
270
|
|
268
|
-
|
271
|
+
cheese.smell.should be > 9000
|
269
272
|
|
270
|
-
and consider which one more clearly describes the desired behavior. The object under test doesn't really have a `should` method, so why should it magically get one during a test?
|
273
|
+
and consider which one more clearly describes the desired behavior. The object under test doesn't really have a `should` method, so why should it magically get one during a test?
|
271
274
|
|
272
275
|
Warning: currently the use of `alias_assert :expect` is **not** compatible with RSpec, since RSpec also defines `expect` as a synonym for `lambda`. If you really want to use `expect` as an alias form `assert`, then use `Wrong.config.alias_assert :expect, :override => true`. See [issue #6](https://github.com/sconover/wrong/issues/6) for more details.
|
273
276
|
|
274
277
|
## Algorithm ##
|
275
278
|
|
276
|
-
So wait a second. How do we do it? Doesn't Ruby have [poor support for AST introspection](http://blog.zenspider.com/2009/04/parsetree-eol.html)? Well, yes, it does, so we cheat: we figure out what file and line the assert block is defined in, then open the file, read the code, and parse it directly using Ryan Davis' amazing [RubyParser](http://parsetree.rubyforge.org/ruby_parser/) and [Ruby2Ruby](http://seattlerb.rubyforge.org/ruby2ruby/). You can bask in the kludge by examining `chunk.rb` and `assert.rb`. If you find some code it can't parse, please send it our way.
|
279
|
+
So wait a second. How do we do it? Doesn't Ruby have [poor support for AST introspection](http://blog.zenspider.com/2009/04/parsetree-eol.html)? Well, yes, it does, so we cheat: we figure out what file and line the assert block is defined in, then open the file, read the code, and parse it directly using Ryan Davis' amazing [RubyParser](http://parsetree.rubyforge.org/ruby_parser/) and [Ruby2Ruby](http://seattlerb.rubyforge.org/ruby2ruby/). You can bask in the kludge by examining `chunk.rb` and `assert.rb`. If you find some code it can't parse, please send it our way.
|
277
280
|
|
278
281
|
Before you get your knickers in a twist about how this is totally unacceptable because it doesn't support this or that use case, here are our caveats and excuses:
|
279
282
|
|
@@ -462,7 +465,7 @@ If you're in Ruby 1.8, you **really** shouldn't do it! But if you do, you can us
|
|
462
465
|
|
463
466
|
## Bugs ##
|
464
467
|
|
465
|
-
*
|
468
|
+
* see Github Issues <http://github.com/sconover/wrong/issues>
|
466
469
|
|
467
470
|
## todo ##
|
468
471
|
|
data/lib/wrong.rb
CHANGED
data/lib/wrong/adapters/rspec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "wrong"
|
2
|
+
require "wrong/terminal"
|
2
3
|
|
3
4
|
if Object.const_defined? :RSpec
|
4
5
|
# RSpec 2
|
@@ -58,6 +59,9 @@ if Object.const_defined? :RSpec
|
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
62
|
+
# tweak terminal width so exceptions wrap properly inside RSpec output
|
63
|
+
Wrong::Terminal.width -= 7
|
64
|
+
|
61
65
|
elsif Object.const_defined? :Spec
|
62
66
|
# RSpec 1
|
63
67
|
Spec::Runner.configure do |config|
|
data/lib/wrong/assert.rb
CHANGED
@@ -5,7 +5,6 @@ require "predicated/to/sentence"
|
|
5
5
|
require "wrong/chunk"
|
6
6
|
require "wrong/config"
|
7
7
|
require "wrong/failure_message"
|
8
|
-
require "wrong/ruby2ruby_patch" # need to patch it after some other stuff loads
|
9
8
|
require "wrong/rainbow"
|
10
9
|
|
11
10
|
module Wrong
|
@@ -68,7 +67,7 @@ module Wrong
|
|
68
67
|
value = !value if valence == :deny
|
69
68
|
if value
|
70
69
|
if Wrong.config[:verbose]
|
71
|
-
code = Wrong::Chunk.from_block(block, depth + 2).code
|
70
|
+
code = Wrong::Chunk.from_block(block, depth + 2).code
|
72
71
|
if Wrong.config[:color]
|
73
72
|
explanation = explanation.color(:blue) if explanation
|
74
73
|
code = code.color(:green)
|
data/lib/wrong/chunk.rb
CHANGED
@@ -2,18 +2,6 @@ require 'ruby_parser'
|
|
2
2
|
require 'ruby2ruby'
|
3
3
|
require 'pp'
|
4
4
|
|
5
|
-
def require_optionally(library)
|
6
|
-
begin
|
7
|
-
require library
|
8
|
-
rescue LoadError => e
|
9
|
-
raise e unless e.message == "no such file to load -- #{library}" or
|
10
|
-
e.message == "cannot load such file -- #{library}" # 1.9.3 changed the error message
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
require_optionally "ParseTree"
|
15
|
-
require_optionally "sourcify"
|
16
|
-
|
17
5
|
require "wrong/config"
|
18
6
|
require "wrong/sexp_ext"
|
19
7
|
require "wrong/capturing"
|
@@ -60,21 +48,11 @@ module Wrong
|
|
60
48
|
end
|
61
49
|
|
62
50
|
def build_sexp
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
rescue Exception => e
|
69
|
-
# sourcify failed, so fall through
|
70
|
-
end
|
71
|
-
|
72
|
-
# next try glomming
|
73
|
-
sexp ||= glom(if @file == "(irb)"
|
74
|
-
IRB.CurrentContext.all_lines
|
75
|
-
else
|
76
|
-
read_source_file(@file)
|
77
|
-
end)
|
51
|
+
glom(if @file == "(irb)"
|
52
|
+
IRB.CurrentContext.all_lines
|
53
|
+
else
|
54
|
+
read_source_file(@file)
|
55
|
+
end)
|
78
56
|
end
|
79
57
|
|
80
58
|
def read_source_file(file)
|
@@ -95,7 +73,6 @@ module Wrong
|
|
95
73
|
while sexp.nil? && line_index + c < lines.size
|
96
74
|
begin
|
97
75
|
@chunk = lines[line_index..line_index+c].join("\n")
|
98
|
-
|
99
76
|
capturing(:stderr) do # new RubyParser is too loud
|
100
77
|
sexp = @parser.parse(@chunk)
|
101
78
|
end
|
@@ -164,148 +141,6 @@ module Wrong
|
|
164
141
|
end
|
165
142
|
end
|
166
143
|
|
167
|
-
def details
|
168
|
-
@details ||= build_details
|
169
|
-
end
|
170
|
-
|
171
|
-
def pretty_value(value, starting_col = 0, indent_wrapped_lines = 6, width = Chunk.terminal_width)
|
172
|
-
# inspected = value.inspect
|
173
|
-
|
174
|
-
# note that if the first line overflows due to the starting column then pp won't wrap it right
|
175
|
-
inspected = PP.pp(value, "", width - starting_col).chomp
|
176
|
-
|
177
|
-
# this bit might be redundant with the pp call now
|
178
|
-
indented = indent_all(6, inspected)
|
179
|
-
if width
|
180
|
-
wrap_and_indent(indented, starting_col, indent_wrapped_lines, width)
|
181
|
-
else
|
182
|
-
indented
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
private
|
187
|
-
|
188
|
-
# todo: move to FailureMessage?
|
189
|
-
def build_details
|
190
|
-
require "wrong/rainbow" if Wrong.config[:color]
|
191
|
-
s = ""
|
192
|
-
parts = self.parts
|
193
|
-
parts.shift # remove the first part, since it's the same as the code
|
194
|
-
|
195
|
-
details = []
|
196
|
-
|
197
|
-
if parts.size > 0
|
198
|
-
parts.each do |part|
|
199
|
-
begin
|
200
|
-
value = eval(part, block.binding)
|
201
|
-
unless part == value.inspect # this skips literals or tautologies
|
202
|
-
if part =~ /\n/m
|
203
|
-
part.gsub!(/\n/, newline(2))
|
204
|
-
part += newline(3)
|
205
|
-
end
|
206
|
-
value = pretty_value(value, (4 + part.length + 4))
|
207
|
-
if Wrong.config[:color]
|
208
|
-
part = part.color(:blue)
|
209
|
-
value = value.color(:magenta)
|
210
|
-
end
|
211
|
-
details << indent(4, part, " is ", value)
|
212
|
-
end
|
213
|
-
rescue Exception => e
|
214
|
-
raises = "raises #{e.class}"
|
215
|
-
if Wrong.config[:color]
|
216
|
-
part = part.color(:blue)
|
217
|
-
raises = raises.bold.color(:red)
|
218
|
-
end
|
219
|
-
formatted_exeption = if e.message and e.message != e.class.to_s
|
220
|
-
indent(4, part, " ", raises, ": ", indent_all(6, e.message))
|
221
|
-
else
|
222
|
-
indent(4, part, " ", raises)
|
223
|
-
end
|
224
|
-
details << formatted_exeption
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
details.uniq!
|
230
|
-
if details.empty?
|
231
|
-
""
|
232
|
-
else
|
233
|
-
"\n" + details.join("\n") + "\n"
|
234
|
-
end
|
235
|
-
|
236
|
-
end
|
237
|
-
|
238
|
-
public # don't know exactly why this needs to be public but eval'ed code can't find it otherwise
|
239
|
-
def indent(indent, *s)
|
240
|
-
"#{" " * indent}#{s.join('')}"
|
241
|
-
end
|
242
|
-
|
243
|
-
def newline(indent)
|
244
|
-
"\n" + self.indent(indent)
|
245
|
-
end
|
246
|
-
|
247
|
-
def indent_all(amount, s)
|
248
|
-
s.gsub("\n", "\n#{indent(amount)}")
|
249
|
-
end
|
250
|
-
|
251
|
-
def wrap_and_indent(indented, starting_col, indent_wrapped_lines, full_width)
|
252
|
-
first_line = true
|
253
|
-
width = full_width - starting_col # the first line is essentially shorter
|
254
|
-
indented.split("\n").map do |line|
|
255
|
-
s = ""
|
256
|
-
while line.length > width
|
257
|
-
s << line[0...width]
|
258
|
-
s << newline(indent_wrapped_lines)
|
259
|
-
line = line[width..-1]
|
260
|
-
if first_line
|
261
|
-
width += starting_col - indent_wrapped_lines
|
262
|
-
first_line = false
|
263
|
-
end
|
264
|
-
end
|
265
|
-
s << line
|
266
|
-
s
|
267
|
-
end.join("\n")
|
268
|
-
end
|
269
|
-
|
270
|
-
# Returns [width, height] of terminal when detected, nil if not detected.
|
271
|
-
# Think of this as a simpler version of Highline's Highline::SystemExtensions.terminal_size()
|
272
|
-
# Lifted from https://github.com/cldwalker/hirb/blob/master/lib/hirb/util.rb#L59
|
273
|
-
#
|
274
|
-
# See also http://stackoverflow.com/questions/2068859/how-to-get-the-width-of-terminal-window-in-ruby
|
275
|
-
# https://github.com/genki/ruby-terminfo/blob/master/lib/terminfo.rb
|
276
|
-
# http://www.mkssoftware.com/docs/man1/stty.1.asp
|
277
|
-
|
278
|
-
|
279
|
-
def self.terminal_size
|
280
|
-
@@terminal_size ||= begin
|
281
|
-
if (ENV['COLUMNS'] =~ /^\d+$/) && (ENV['LINES'] =~ /^\d+$/)
|
282
|
-
[ENV['COLUMNS'].to_i, ENV['LINES'].to_i]
|
283
|
-
elsif (RUBY_PLATFORM =~ /java/ || (!STDIN.tty? && ENV['TERM'])) && command_exists?('tput')
|
284
|
-
[`tput cols`.to_i, `tput lines`.to_i]
|
285
|
-
elsif STDIN.tty? && command_exists?('stty')
|
286
|
-
`stty size`.scan(/\d+/).map { |s| s.to_i }.reverse
|
287
|
-
else
|
288
|
-
nil
|
289
|
-
end
|
290
|
-
rescue
|
291
|
-
nil
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
def self.terminal_width
|
296
|
-
(@terminal_width ||= nil) || (terminal_size && terminal_size.first) || 80
|
297
|
-
end
|
298
|
-
|
299
|
-
def self.terminal_width= forced_with
|
300
|
-
@terminal_width = forced_with
|
301
|
-
end
|
302
|
-
|
303
|
-
# Determines if a shell command exists by searching for it in ENV['PATH'].
|
304
|
-
def self.command_exists?(command)
|
305
|
-
ENV['PATH'].split(File::PATH_SEPARATOR).any? {|d| File.exists? File.join(d, command) }
|
306
|
-
end
|
307
|
-
|
308
|
-
|
309
144
|
end
|
310
145
|
|
311
146
|
end
|
data/lib/wrong/close_to.rb
CHANGED
@@ -1,8 +1,14 @@
|
|
1
1
|
module Wrong
|
2
2
|
module CloseTo
|
3
3
|
def close_to?(other, tolerance = 0.001)
|
4
|
-
|
4
|
+
if respond_to? :to_f
|
5
|
+
(self.to_f - other.to_f).abs < tolerance
|
6
|
+
elsif respond_to? :to_time
|
7
|
+
self.to_time.close_to?( other.to_time, tolerance)
|
8
|
+
end
|
5
9
|
end
|
6
10
|
end
|
7
11
|
Numeric.send :include, CloseTo
|
12
|
+
Date.send :include, CloseTo
|
13
|
+
Time.send :include, CloseTo
|
8
14
|
end
|
data/lib/wrong/config.rb
CHANGED
@@ -10,7 +10,7 @@ module Wrong
|
|
10
10
|
end
|
11
11
|
Config.new settings
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def self.config
|
15
15
|
@config ||= load_config
|
16
16
|
end
|
@@ -72,8 +72,8 @@ module Wrong
|
|
72
72
|
self[:aliases][:deny]
|
73
73
|
end
|
74
74
|
|
75
|
-
def
|
76
|
-
assert_method_names + deny_method_names
|
75
|
+
def hidden_methods
|
76
|
+
assert_method_names + deny_method_names + [:eventually]
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
data/lib/wrong/d.rb
CHANGED
@@ -21,6 +21,7 @@ module Wrong
|
|
21
21
|
|
22
22
|
# look for a "d" inside the block
|
23
23
|
sexp.each_subexp do |subexp|
|
24
|
+
#sexp.deep_each do |subexp| # todo: try to use deep_each
|
24
25
|
if subexp.d?
|
25
26
|
sexp = subexp[3] # swap in the block part of the nested d call
|
26
27
|
end
|
@@ -28,7 +29,7 @@ module Wrong
|
|
28
29
|
|
29
30
|
code = sexp.to_ruby
|
30
31
|
value = eval(code, block.binding, called_from[0], called_from[1].to_i)
|
31
|
-
width =
|
32
|
+
width = Terminal.width
|
32
33
|
value = PP.pp(value, "", width - (code.size + 3)).chomp
|
33
34
|
|
34
35
|
if Wrong.config[:color]
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require "wrong/chunk"
|
2
|
+
require "wrong/terminal"
|
3
|
+
|
1
4
|
module Wrong
|
2
5
|
class FailureMessage
|
3
6
|
@@formatters = []
|
@@ -40,7 +43,6 @@ module Wrong
|
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
43
|
-
|
44
46
|
attr_accessor :chunk, :valence, :explanation
|
45
47
|
|
46
48
|
def initialize(chunk, valence, explanation)
|
@@ -57,20 +59,89 @@ module Wrong
|
|
57
59
|
message << basic
|
58
60
|
|
59
61
|
formatted_message = if predicate && !(predicate.is_a? Predicated::Conjunction)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
62
|
+
if formatter = FailureMessage.formatter_for(predicate)
|
63
|
+
colored(:bold, formatter.describe)
|
64
|
+
end
|
65
|
+
end
|
64
66
|
|
65
|
-
unless
|
67
|
+
unless details.empty? and formatted_message.nil?
|
66
68
|
message << ", but"
|
67
69
|
end
|
68
70
|
|
69
71
|
message << formatted_message if formatted_message
|
70
|
-
message <<
|
72
|
+
message << details unless details.empty?
|
71
73
|
message
|
72
74
|
end
|
73
75
|
|
76
|
+
def details
|
77
|
+
@details ||= begin
|
78
|
+
require "wrong/rainbow" if Wrong.config[:color]
|
79
|
+
s = ""
|
80
|
+
parts = chunk.parts
|
81
|
+
|
82
|
+
parts.shift while parts.first == "()" # the parser adds this sometimes
|
83
|
+
parts.shift # remove the first part, since it's the same as the code
|
84
|
+
|
85
|
+
details = []
|
86
|
+
|
87
|
+
if parts.size > 0
|
88
|
+
parts.each do |part|
|
89
|
+
begin
|
90
|
+
value = eval(part, chunk.block.binding)
|
91
|
+
unless part == value.inspect # this skips literals or tautologies
|
92
|
+
if part =~ /\n/m
|
93
|
+
part.gsub!(/\n/, newline(2))
|
94
|
+
part += newline(3)
|
95
|
+
end
|
96
|
+
value = pretty_value(value, (4 + part.length + 4))
|
97
|
+
if Wrong.config[:color]
|
98
|
+
part = part.color(:blue)
|
99
|
+
value = value.color(:magenta)
|
100
|
+
end
|
101
|
+
details << indent(4, part, " is ", value)
|
102
|
+
end
|
103
|
+
rescue Exception => e
|
104
|
+
raises = "raises #{e.class}"
|
105
|
+
if Wrong.config[:color]
|
106
|
+
part = part.color(:blue)
|
107
|
+
raises = raises.bold.color(:red)
|
108
|
+
end
|
109
|
+
formatted_exeption = if e.message and e.message != e.class.to_s
|
110
|
+
indent(4, part, " ", raises, ": ", indent_all(6, e.message))
|
111
|
+
else
|
112
|
+
indent(4, part, " ", raises)
|
113
|
+
end
|
114
|
+
details << formatted_exeption
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
details.uniq!
|
120
|
+
if details.empty?
|
121
|
+
""
|
122
|
+
else
|
123
|
+
"\n" + details.join("\n") + "\n"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
# todo: use awesome_print
|
130
|
+
def pretty_value(value, starting_col = 0, indent_wrapped_lines = 6, width = Terminal.width)
|
131
|
+
# inspected = value.inspect
|
132
|
+
|
133
|
+
# note that if the first line overflows due to the starting column then pp won't wrap it right
|
134
|
+
inspected = PP.pp(value, "", width - starting_col).chomp
|
135
|
+
|
136
|
+
# this bit might be redundant with the pp call now
|
137
|
+
indented = indent_all(6, inspected)
|
138
|
+
if width
|
139
|
+
wrap_and_indent(indented, starting_col, indent_wrapped_lines, width)
|
140
|
+
else
|
141
|
+
indented
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
74
145
|
protected
|
75
146
|
def code
|
76
147
|
@code ||= chunk.code
|
@@ -98,5 +169,36 @@ module Wrong
|
|
98
169
|
end
|
99
170
|
end
|
100
171
|
|
172
|
+
def indent(indent, *s)
|
173
|
+
"#{" " * indent}#{s.join('')}"
|
174
|
+
end
|
175
|
+
|
176
|
+
def newline(indent)
|
177
|
+
"\n" + self.indent(indent)
|
178
|
+
end
|
179
|
+
|
180
|
+
def indent_all(amount, s)
|
181
|
+
s.gsub("\n", "\n#{indent(amount)}")
|
182
|
+
end
|
183
|
+
|
184
|
+
def wrap_and_indent(indented, starting_col, indent_wrapped_lines, full_width)
|
185
|
+
first_line = true
|
186
|
+
width = full_width - starting_col # the first line is essentially shorter
|
187
|
+
indented.split("\n").map do |line|
|
188
|
+
s = ""
|
189
|
+
while line.length > width
|
190
|
+
s << line[0...width]
|
191
|
+
s << newline(indent_wrapped_lines)
|
192
|
+
line = line[width..-1]
|
193
|
+
if first_line
|
194
|
+
width += starting_col - indent_wrapped_lines
|
195
|
+
first_line = false
|
196
|
+
end
|
197
|
+
end
|
198
|
+
s << line
|
199
|
+
s
|
200
|
+
end.join("\n")
|
201
|
+
end
|
202
|
+
|
101
203
|
end
|
102
204
|
end
|