forked from mconnell/ruby_koans_online
-
Notifications
You must be signed in to change notification settings - Fork 0
/
string.rb
175 lines (166 loc) · 5.98 KB
/
string.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
require 'cgi'
class String
TEXT_AREA_MATCHER = /_[\w_]+?\.rb_\n([\w\s\#\:\.\(\)\@\,\=]+?\n)\s*_[\w_]+?\.rb_/
FILL_ME_IN = /_(?:textarea)?(?:n)?__*/
def remove_require_lines
self.split("\n").reject{|line| line.start_with? 'require' }.join("\n")
end
def preify
self.gsub('<','<').gsub('>','>').gsub("\n","<br/>").gsub("\s"," ")
end
def swap_user_values(input_values, request, session)
count = 0
method_area = false
method_name = nil
method_indentation = 0
in_ruby_v = nil
in_ruby_indentation = 0
in_correct_ruby_v = true
default_textarea_contents = ''
session_code_match_name = ''
self.gsub(TEXT_AREA_MATCHER) do |match|
default_textarea_contents = $1
session_code_match_name = CGI.unescape((match.match(/_[\w_]+?\.rb_/)||[])[0])
"_textarea_"
end.split("\n").map do |line|
if match = line.match(/^(\s{2}*)in_ruby_version.*[\"\'](.*)[\"\']/)
in_ruby_indentation = match[1].size
in_ruby_v = match[2]
in_correct_ruby_v = in_ruby_v.include? "1.8"
next
elsif in_ruby_v
if line.match(/^\s{#{in_ruby_indentation}}end/)
in_ruby_v = nil
in_ruby_indentation = 0
in_correct_ruby_v = true
next
else
line = line[in_ruby_indentation..-1].to_s
end
end
next unless in_correct_ruby_v
if match = line.match(/^(\s{2}*)def test_/)
method_area = true
method_indentation = match[1].size
method_name = (methodx = line.match(/test_\S*/)) && methodx[0]
elsif line.start_with?(/\s{#{method_indentation}}end/) && method_area
method_area = false
method_name = nil
end
if line.strip.start_with? "#"
line
else
line.gsub('__send__', '**send**').gsub(FILL_ME_IN) do |match|
if %w{test_assert_truth test_assert_with_message}.include?(method_name) &&
(input_values[count].nil? || input_values[count].empty?)
input_values[count] = 'false'
end
x = if input_values[count].to_s == ""
if match.include?('textarea')
if previously_entered = session[session_code_match_name.to_sym]
request[:used_previous_session_code] = true
previously_entered
else
default_textarea_contents
end
elsif match.include? 'n'
999999
else
match
end
else
"#{input_values[count]}"
end
session[session_code_match_name.to_sym] = x unless session_code_match_name.empty?
count = count + 1
x
end.gsub('**send**', '__send__')
end
end.compact.join("\n")
end
def swap_input_fields(input_values, passes, failures, session={})
failures ||= {}
count = 0
method_count = 0
method_area = false
method_name = nil
method_indentation = 0
in_ruby_v = nil
in_ruby_indentation = 0
in_correct_ruby_v = true
default_textarea_contents = ''
session_code_match_name = ''
self.gsub(TEXT_AREA_MATCHER) do |match|
default_textarea_contents = $1
session_code_match_name = (match.match(/_[\w_]+?\.rb_/)||[])[0]
"_textarea_"
end.gsub("\s", " ").gsub("<","<").split("\n").map do |line|
true_line = line.gsub(' ',' ')
if match = true_line.match(/^(\s{2}*)in_ruby_version.*[\"\'](.*)[\"\']/)
in_ruby_indentation = match[1].size
in_ruby_v = match[2]
in_correct_ruby_v = in_ruby_v.include? "1.8"
next
elsif in_ruby_v
if true_line.match(/^\s{#{in_ruby_indentation}}end/)
in_ruby_v = nil
in_ruby_indentation = 0
in_correct_ruby_v = true
next
else
line = line[(in_ruby_indentation*(' '.size))..-1].to_s
true_line = line.gsub(' ',' ')
end
end
next unless in_correct_ruby_v
if match = true_line.match(/^(\s{2}*)def test_/)
method_area = true
method_indentation = match[1].size
method_count = method_count + 1
method_name = (methodx = true_line.match(/test_\S*/)) && methodx[0]
failure = failures[method_name.to_sym]
"#{fail_message(failure)}
<div nowrap='nowrap' class='#{(failure || failures[:epic_fail]) ? 'failed' : 'passed'}'>
#{line}"
elsif method_area && true_line.match(/^\s{#{method_indentation}}end/)
method_area = false
"#{line}</div>"
elsif line.gsub(" ","").start_with?("#")
line
else
line.gsub(/__send__/, '**send**').gsub(FILL_ME_IN) do |match|
if %w{test_assert_truth test_assert_with_message}.include?(method_name) &&
(input_values[count].nil? || input_values[count].empty?)
x = 'false'
else
x = input_values[count].to_s
end
count = count + 1
if match.include? 'textarea'
val = if x.to_s.empty?
sess = session[session_code_match_name.to_sym]
(sess && sess != '__') ? sess : default_textarea_contents
else
x
end
"<textarea class='koanInput' name='input[]' cols='80' rows='10'>#{val.gsub("'", "'").gsub(/\r?\n/, "\r")}</textarea>"
else
x = '999999' if(x.empty? && match.include?('n'))
"<input class='koanInput' type='text' name='input[]' value='#{x.gsub("'", "'")}\' />"
end
end.gsub('**send**', '__send__')
end
end.compact.join('<br/>')
end
def fail_message(failure)
return nil if failure.nil?
failure.message.gsub!(/KoanArena::UniqueRun[\d]+::/, '')
if failure.message.include? "FILL ME IN"
" Please meditate on the following.".preify
elsif failure.message.include? "undefined local"
failure.message.split("for #<").first.preify
else
" The answers which you seek:\n #{failure.message.gsub("\n"," ")}".preify
end
end
end