texttube_baby 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/Gemfile +9 -0
- data/LICENCE.txt +22 -0
- data/README.md +242 -0
- data/Rakefile +2 -0
- data/lib/ext/blank.rb +21 -0
- data/lib/texttube/baby.rb +5 -0
- data/lib/texttube/baby/coderay.rb +68 -0
- data/lib/texttube/baby/embedding_audio.rb +62 -0
- data/lib/texttube/baby/embedding_video.rb +124 -0
- data/lib/texttube/baby/inside_block.rb +35 -0
- data/lib/texttube/baby/link_reffing.rb +147 -0
- data/lib/texttube/baby/spiffing.rb +44 -0
- data/lib/texttube/baby/version.rb +5 -0
- data/spec/coderay_spec.rb +86 -0
- data/spec/embedding_audio_spec.rb +41 -0
- data/spec/embedding_video_spec.rb +35 -0
- data/spec/inside_block_spec.rb +34 -0
- data/spec/link_reffing_spec.rb +100 -0
- data/spec/markdownfilters_spec.rb +279 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/spiffing_spec.rb +49 -0
- data/texttube_baby.gemspec +25 -0
- metadata +145 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require_relative "../lib/texttube/baby/embedding_audio.rb"
|
5
|
+
|
6
|
+
|
7
|
+
module TextTube # for convenience
|
8
|
+
module Baby
|
9
|
+
|
10
|
+
describe EmbeddingAudio do
|
11
|
+
context "Given some text" do
|
12
|
+
let(:content) { "[audio[a24.m4a|A24]]" }
|
13
|
+
let(:expected) {
|
14
|
+
%q[<div class='audio'><h3>A24</h3><audio preload='metadata' controls='controls'><source src='/streams/a24.m4a' type='audio/m4a' /><source src='/streams/a24.ogg' type='audio/ogg' />Your browser does not support HTML5, update your browser you fool!</audio></div>]
|
15
|
+
}
|
16
|
+
context "containing valid extended markdown for audio" do
|
17
|
+
context "with no options" do
|
18
|
+
subject { EmbeddingAudio.run content }
|
19
|
+
it { should_not be_nil }
|
20
|
+
it { should be == expected }
|
21
|
+
end
|
22
|
+
context "with src_base given as an option" do
|
23
|
+
subject { EmbeddingAudio.run content, {src_base: "/files/" } }
|
24
|
+
it { should_not be_nil }
|
25
|
+
it { should_not == expected }
|
26
|
+
it { should match(%r{^.+\ssrc\='/files/\S+?'\s.+$}) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
context "containing invalid extended markdown for audio" do
|
30
|
+
let(:content) { "audio[a24.m4a|A24]]" }
|
31
|
+
subject { EmbeddingAudio.run content }
|
32
|
+
it { should_not be_nil }
|
33
|
+
it { should_not be == expected }
|
34
|
+
it { should == content }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end # describe
|
39
|
+
|
40
|
+
end
|
41
|
+
end # for inconvenience
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require_relative "../lib/texttube/baby/embedding_video.rb"
|
5
|
+
|
6
|
+
|
7
|
+
module TextTube # for convenience
|
8
|
+
module Baby
|
9
|
+
|
10
|
+
describe EmbeddingVideo do
|
11
|
+
context "Given some text" do
|
12
|
+
let(:content) { "[video_large[//youtu.be/1Xhdy9zBEws|Royksopp, Remind Me]]" }
|
13
|
+
let(:expected) {
|
14
|
+
%q[<iframe title="YouTube video player" class="youtube-player" type="text/html" width="853" height="510" src="//www.youtube.com/embed/1Xhdy9zBEws" frameborder="0"></iframe>]
|
15
|
+
}
|
16
|
+
context "containing valid extended markdown for video" do
|
17
|
+
context "with no options" do
|
18
|
+
subject { EmbeddingVideo.run content }
|
19
|
+
it { should_not be_nil }
|
20
|
+
it { should be == expected }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
context "containing invalid extended markdown for video" do
|
24
|
+
let(:content) { "video[a24.m4a|A24]]" }
|
25
|
+
subject { EmbeddingVideo.run content }
|
26
|
+
it { should_not be_nil }
|
27
|
+
it { should_not be == expected }
|
28
|
+
it { should == content }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end # describe
|
33
|
+
|
34
|
+
end
|
35
|
+
end # for inconvenience
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative "../lib/texttube/baby/inside_block.rb"
|
3
|
+
|
4
|
+
describe "InsideBlock" do
|
5
|
+
let(:content) { <<HTML
|
6
|
+
<div class='wrapper' id='sidebar' markdown='1'>
|
7
|
+
## This is a sidebar ##
|
8
|
+
|
9
|
+
* Written
|
10
|
+
* in
|
11
|
+
* markdown
|
12
|
+
|
13
|
+
Sometimes this is useful.
|
14
|
+
</div>
|
15
|
+
HTML
|
16
|
+
}
|
17
|
+
let(:expected) { <<HTML
|
18
|
+
<div class="wrapper" id="sidebar">
|
19
|
+
<h2>This is a sidebar</h2>
|
20
|
+
|
21
|
+
<ul>
|
22
|
+
<li>Written</li>
|
23
|
+
<li>in</li>
|
24
|
+
<li>markdown</li>
|
25
|
+
</ul>
|
26
|
+
|
27
|
+
|
28
|
+
<p>Sometimes this is useful.</p>
|
29
|
+
</div>
|
30
|
+
HTML
|
31
|
+
}
|
32
|
+
subject { TextTube::InsideBlock.run content }
|
33
|
+
it { should == expected }
|
34
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require_relative "../lib/texttube/baby/link_reffing.rb"
|
5
|
+
|
6
|
+
module TextTube
|
7
|
+
module Baby # convience
|
8
|
+
|
9
|
+
describe LinkReffing do
|
10
|
+
context "Given some text" do
|
11
|
+
context "With a link to be reffed in it" do
|
12
|
+
shared_examples "outputting links" do
|
13
|
+
it { should_not be_nil }
|
14
|
+
it { should == expected }
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:content) { "The UtterFAIL website[[http://utterfail.info|UtterFAIL!]] is good. My blog[[http://iainbarnett.me.uk|My blog]] is also good." }
|
18
|
+
|
19
|
+
context "and no options" do
|
20
|
+
subject { TextTube::Baby::LinkReffing.run content }
|
21
|
+
let(:expected) { s = <<HTML
|
22
|
+
The UtterFAIL website[⁰](#0 "Jump to reference") is good. My blog[¹](#1 "Jump to reference") is also good.
|
23
|
+
<div markdown='1' id='reflinks'>
|
24
|
+
<a name="0"></a>[0] [http://utterfail.info](http://utterfail.info "http://utterfail.info") UtterFAIL!
|
25
|
+
|
26
|
+
|
27
|
+
<a name="1"></a>[1] [http://iainbarnett.me.uk](http://iainbarnett.me.uk "http://iainbarnett.me.uk") My blog
|
28
|
+
|
29
|
+
</div>
|
30
|
+
HTML
|
31
|
+
s.strip
|
32
|
+
}
|
33
|
+
include_examples "outputting links"
|
34
|
+
end
|
35
|
+
context "and an option not to ref the link (i.e. inline)" do
|
36
|
+
let(:expected) {
|
37
|
+
"The UtterFAIL website [UtterFAIL!](http://utterfail.info) is good. My blog [My blog](http://iainbarnett.me.uk) is also good."
|
38
|
+
}
|
39
|
+
subject {
|
40
|
+
TextTube::Baby::LinkReffing.run content, kind: :inline
|
41
|
+
}
|
42
|
+
include_examples "outputting links"
|
43
|
+
context "and use HTML" do
|
44
|
+
let(:expected) {
|
45
|
+
%Q$The UtterFAIL website <a href="http://utterfail.info">UtterFAIL!</a> is good. My blog <a href="http://iainbarnett.me.uk">My blog</a> is also good.$
|
46
|
+
}
|
47
|
+
subject {
|
48
|
+
TextTube::Baby::LinkReffing.run content, kind: :inline, format: :html
|
49
|
+
}
|
50
|
+
include_examples "outputting links"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
context "and an option to output a link as HTML" do
|
54
|
+
let(:expected) { s = <<HTML
|
55
|
+
The UtterFAIL website<a href="#0" title="Jump to reference">⁰</a> is good. My blog<a href="#1" title="Jump to reference">¹</a> is also good.
|
56
|
+
<div markdown='1' id='reflinks'>
|
57
|
+
<a name="0"></a>[0] [http://utterfail.info](http://utterfail.info "http://utterfail.info") UtterFAIL!
|
58
|
+
|
59
|
+
|
60
|
+
<a name="1"></a>[1] [http://iainbarnett.me.uk](http://iainbarnett.me.uk "http://iainbarnett.me.uk") My blog
|
61
|
+
|
62
|
+
</div>
|
63
|
+
HTML
|
64
|
+
s.strip
|
65
|
+
}
|
66
|
+
subject { TextTube::Baby::LinkReffing.run content, format: :html }
|
67
|
+
include_examples "outputting links"
|
68
|
+
end
|
69
|
+
context "and an option to not show the link at all" do
|
70
|
+
let(:expected) { s = <<HTML
|
71
|
+
The UtterFAIL website is good. My blog is also good.
|
72
|
+
HTML
|
73
|
+
s.strip
|
74
|
+
}
|
75
|
+
subject {
|
76
|
+
TextTube::Baby::LinkReffing.run content, kind: :none
|
77
|
+
}
|
78
|
+
include_examples "outputting links"
|
79
|
+
end
|
80
|
+
end # context
|
81
|
+
|
82
|
+
context "With no link to be reffed in it" do
|
83
|
+
let(:content) { %Q$The [UtterFAIL website](http://utterfail.info/ "UtterFAIL!") is good.$ }
|
84
|
+
let(:expected) { content }
|
85
|
+
subject { TextTube::Baby::LinkReffing.run content }
|
86
|
+
it { should_not be_nil }
|
87
|
+
it { should == expected }
|
88
|
+
end # context
|
89
|
+
end # context
|
90
|
+
|
91
|
+
context "Given no text" do
|
92
|
+
subject { TextTube::Baby::LinkReffing.run "" }
|
93
|
+
it { should_not be_nil }
|
94
|
+
it { should == "" }
|
95
|
+
end # context
|
96
|
+
|
97
|
+
end # describe LinkReffing
|
98
|
+
|
99
|
+
end #convenience
|
100
|
+
end # module
|
@@ -0,0 +1,279 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'texttube/base.rb'
|
5
|
+
|
6
|
+
describe "TextTube" do
|
7
|
+
let(:content) { <<MARKDOWN
|
8
|
+
## The Rainfall Problem ##
|
9
|
+
|
10
|
+
I read of a test given to students to see if they understand the concepts in the first part of a computer science course. It was in an interesting paper called *What Makes Code Hard to Understand?*[[http://arxiv.org/abs/1304.5257|What Makes Code Hard to Understand? Michael Hansen, Robert L. Goldstone, Andrew Lumsdaine]].
|
11
|
+
|
12
|
+
> To solve it, students must write a program that averages a list of numbers (rainfall amounts), where the list is terminated with a specific value – e.g., a negative number or 999999.
|
13
|
+
|
14
|
+
Of course, reading about the problem I immediately wanted to try it, but even though the idea of posing the problem was to test the understanding of loops, the problem lends itself naturally to a recursive solution, and that's much more interesting than a boring old loop! I realised it wouldn't run well in Ruby but decided to write it anyway:
|
15
|
+
|
16
|
+
::::ruby
|
17
|
+
def rainfall(droplets,total=0,measures=1,limit=99_999)
|
18
|
+
return total.to_f.div measures if droplets == limit
|
19
|
+
unless droplets < 0
|
20
|
+
total += droplets
|
21
|
+
measures += 1
|
22
|
+
end
|
23
|
+
rainfall rand(limit + 1), total, measures
|
24
|
+
end
|
25
|
+
|
26
|
+
Normally I'd start this off with a random number, but just to make it clear that it works I started with the termination number. Then, I reran it until it worked. It gives you an idea of how poor Ruby is at recursion.
|
27
|
+
|
28
|
+
::::shell
|
29
|
+
rainfall 99_999
|
30
|
+
# => 0
|
31
|
+
rainfall 99_998
|
32
|
+
SystemStackError: stack level too deep
|
33
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
34
|
+
Maybe IRB bug!
|
35
|
+
rainfall 99_998
|
36
|
+
SystemStackError: stack level too deep
|
37
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
38
|
+
Maybe IRB bug!
|
39
|
+
rainfall 99_998
|
40
|
+
SystemStackError: stack level too deep
|
41
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
42
|
+
Maybe IRB bug!
|
43
|
+
rainfall 99_998
|
44
|
+
SystemStackError: stack level too deep
|
45
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
46
|
+
Maybe IRB bug!
|
47
|
+
rainfall 99_998
|
48
|
+
# => 49693
|
49
|
+
|
50
|
+
Just to be clear, I ran this with Ruby 2.0.0-rc2 as well with the same results. It's a pity that Ruby fails at this kind of thing, because it is such an elegant and useful language that seems to have borrowed the best of many other niche languages. Recursion is often the most elegant *and* performant[[http://dictionary.cambridge.org/dictionary/british/pedant|If you're one of these then you won't like that I made a word up. Unfortunately for you, I'm British, which means that I understand that English is a living language, it is my tool not my master, and it has a long history of being changed to suit the speaker or writer. This is one such case.]] solution.
|
51
|
+
MARKDOWN
|
52
|
+
}
|
53
|
+
context "with simple examples" do
|
54
|
+
before :all do
|
55
|
+
module AFilter
|
56
|
+
extend TextTube::Filterable
|
57
|
+
|
58
|
+
filter_with :double do |text|
|
59
|
+
text * 2
|
60
|
+
end
|
61
|
+
|
62
|
+
filter_with :triple do |text|
|
63
|
+
text * 3
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module BFil
|
68
|
+
extend TextTube::Filterable
|
69
|
+
|
70
|
+
filter_with :spacial do |current,options|
|
71
|
+
current.split(//).join " "
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class NeuS < TextTube::Base
|
76
|
+
register BFil
|
77
|
+
register AFilter
|
78
|
+
register do
|
79
|
+
filter_with :dashes do |text|
|
80
|
+
"---#{text}---"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
let(:n) { NeuS.new "abc" }
|
86
|
+
subject { n }
|
87
|
+
it { should == "abc" }
|
88
|
+
its(:filters) { should =~ [:spacial, :dashes, :double, :triple] }
|
89
|
+
its(:filter) { should == "---a b ca b ca b ca b ca b ca b c---" }
|
90
|
+
context "ordering" do
|
91
|
+
context "given one filter" do
|
92
|
+
subject { n.filter :spacial }
|
93
|
+
it { should == "a b c" }
|
94
|
+
end
|
95
|
+
context "given several filters but not all" do
|
96
|
+
subject { n.filter :spacial, :dashes }
|
97
|
+
it { should == "---a b c---" }
|
98
|
+
end
|
99
|
+
context "given several filters in a different order" do
|
100
|
+
subject { n.filter :dashes, :double, :spacial, :triple }
|
101
|
+
it { should == "- - - a b c - - - - - - a b c - - -- - - a b c - - - - - - a b c - - -- - - a b c - - - - - - a b c - - -" }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
context "Real examples" do
|
106
|
+
require_relative "../lib/texttube.rb"
|
107
|
+
require 'rdiscount'
|
108
|
+
|
109
|
+
context "An article that needs all the filters" do
|
110
|
+
before :all do
|
111
|
+
TextTube.load_all_filters
|
112
|
+
class MyFilter < TextTube::Base
|
113
|
+
register TextTube::Coderay
|
114
|
+
register TextTube::LinkReffing
|
115
|
+
register TextTube::EmbeddingAudio
|
116
|
+
register TextTube::EmbeddingVideo
|
117
|
+
register TextTube::InsideBlock
|
118
|
+
register do
|
119
|
+
filter_with :rdiscount do |text|
|
120
|
+
RDiscount.new(text).to_html
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
let(:expected) { <<HTML
|
126
|
+
<h2>The Rainfall Problem</h2>
|
127
|
+
|
128
|
+
<p>I read of a test given to students to see if they understand the concepts in the first part of a computer science course. It was in an interesting paper called <em>What Makes Code Hard to Understand?</em><a href="#0" title="Jump to reference">⁰</a>.</p>
|
129
|
+
|
130
|
+
<blockquote><p>To solve it, students must write a program that averages a list of numbers (rainfall amounts), where the list is terminated with a specific value – e.g., a negative number or 999999.</p></blockquote>
|
131
|
+
|
132
|
+
<p>Of course, reading about the problem I immediately wanted to try it, but even though the idea of posing the problem was to test the understanding of loops, the problem lends itself naturally to a recursive solution, and that's much more interesting than a boring old loop! I realised it wouldn't run well in Ruby but decided to write it anyway:</p>
|
133
|
+
|
134
|
+
<pre><code class="CodeRay"><span class="keyword">def</span> <span class="function">rainfall</span>(droplets,total=<span class="integer">0</span>,measures=<span class="integer">1</span>,limit=<span class="integer">99_999</span>)
|
135
|
+
<span class="keyword">return</span> total.to_f.div measures <span class="keyword">if</span> droplets == limit
|
136
|
+
<span class="keyword">unless</span> droplets < <span class="integer">0</span>
|
137
|
+
total += droplets
|
138
|
+
measures += <span class="integer">1</span>
|
139
|
+
<span class="keyword">end</span>
|
140
|
+
rainfall rand(limit + <span class="integer">1</span>), total, measures
|
141
|
+
<span class="keyword">end</span></code></pre>
|
142
|
+
|
143
|
+
<p>Normally I'd start this off with a random number, but just to make it clear that it works I started with the termination number. Then, I reran it until it worked. It gives you an idea of how poor Ruby is at recursion.</p>
|
144
|
+
|
145
|
+
<pre><code class="CodeRay">rainfall 99_999
|
146
|
+
# => 0
|
147
|
+
rainfall 99_998
|
148
|
+
SystemStackError: stack level too deep
|
149
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
150
|
+
Maybe IRB bug!
|
151
|
+
rainfall 99_998
|
152
|
+
SystemStackError: stack level too deep
|
153
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
154
|
+
Maybe IRB bug!
|
155
|
+
rainfall 99_998
|
156
|
+
SystemStackError: stack level too deep
|
157
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
158
|
+
Maybe IRB bug!
|
159
|
+
rainfall 99_998
|
160
|
+
SystemStackError: stack level too deep
|
161
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
162
|
+
Maybe IRB bug!
|
163
|
+
rainfall 99_998
|
164
|
+
# => 49693</code></pre>
|
165
|
+
|
166
|
+
<p>Just to be clear, I ran this with Ruby 2.0.0-rc2 as well with the same results. It's a pity that Ruby fails at this kind of thing, because it is such an elegant and useful language that seems to have borrowed the best of many other niche languages. Recursion is often the most elegant <em>and</em> performant<a href="#1" title="Jump to reference">¹</a> solution.</p>
|
167
|
+
|
168
|
+
<div id="reflinks">
|
169
|
+
<p><a name="0"></a>[0] <a href="http://arxiv.org/abs/1304.5257" title="http://arxiv.org/abs/1304.5257">http://arxiv.org/abs/1304.5257</a> What Makes Code Hard to Understand? Michael Hansen, Robert L. Goldstone, Andrew Lumsdaine</p>
|
170
|
+
|
171
|
+
<p><a name="1"></a>[1] <a href="http://dictionary.cambridge.org/dictionary/british/pedant" title="http://dictionary.cambridge.org/dictionary/british/pedant">http://dictionary.cambridge.org/dictionary/br...</a> If you're one of these then you won't like that I made a word up. Unfortunately for you, I'm British, which means that I understand that English is a living language, it is my tool not my master, and it has a long history of being changed to suit the speaker or writer. This is one such case.</p>
|
172
|
+
</div>
|
173
|
+
|
174
|
+
HTML
|
175
|
+
}
|
176
|
+
let(:my_f) { MyFilter.new content }
|
177
|
+
subject { my_f.filter :embeddingvideo, :embeddingaudio, :linkreffing, :rdiscount, :coderay, :insideblock }
|
178
|
+
it { should == expected }
|
179
|
+
|
180
|
+
describe "With options" do
|
181
|
+
context "Passed to the class" do
|
182
|
+
before :all do
|
183
|
+
MyFilter.options.merge! :linkreffing => {kind: :none}
|
184
|
+
end
|
185
|
+
subject { MyFilter.new(content).filter :embeddingvideo, :embeddingaudio, :linkreffing, :rdiscount, :coderay, :insideblock }
|
186
|
+
it { should_not == expected }
|
187
|
+
|
188
|
+
context "and passed to filter" do
|
189
|
+
subject { MyFilter.new(content).filter :embeddingvideo, :embeddingaudio, :linkreffing, :rdiscount, :coderay, :insideblock, :linkreffing => {kind: :reference} }
|
190
|
+
it { should == expected }
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "An atom feed that only needs some of the filters" do
|
197
|
+
let(:expected) { <<EXPECTED
|
198
|
+
<h2>The Rainfall Problem</h2>
|
199
|
+
|
200
|
+
<p>I read of a test given to students to see if they understand the concepts in the first part of a computer science course. It was in an interesting paper called <em>What Makes Code Hard to Understand?</em>.</p>
|
201
|
+
|
202
|
+
<blockquote><p>To solve it, students must write a program that averages a list of numbers (rainfall amounts), where the list is terminated with a specific value – e.g., a negative number or 999999.</p></blockquote>
|
203
|
+
|
204
|
+
<p>Of course, reading about the problem I immediately wanted to try it, but even though the idea of posing the problem was to test the understanding of loops, the problem lends itself naturally to a recursive solution, and that's much more interesting than a boring old loop! I realised it wouldn't run well in Ruby but decided to write it anyway:</p>
|
205
|
+
|
206
|
+
<pre><code>::::ruby
|
207
|
+
def rainfall(droplets,total=0,measures=1,limit=99_999)
|
208
|
+
return total.to_f.div measures if droplets == limit
|
209
|
+
unless droplets < 0
|
210
|
+
total += droplets
|
211
|
+
measures += 1
|
212
|
+
end
|
213
|
+
rainfall rand(limit + 1), total, measures
|
214
|
+
end
|
215
|
+
</code></pre>
|
216
|
+
|
217
|
+
<p>Normally I'd start this off with a random number, but just to make it clear that it works I started with the termination number. Then, I reran it until it worked. It gives you an idea of how poor Ruby is at recursion.</p>
|
218
|
+
|
219
|
+
<pre><code>::::shell
|
220
|
+
rainfall 99_999
|
221
|
+
# => 0
|
222
|
+
rainfall 99_998
|
223
|
+
SystemStackError: stack level too deep
|
224
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
225
|
+
Maybe IRB bug!
|
226
|
+
rainfall 99_998
|
227
|
+
SystemStackError: stack level too deep
|
228
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
229
|
+
Maybe IRB bug!
|
230
|
+
rainfall 99_998
|
231
|
+
SystemStackError: stack level too deep
|
232
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
233
|
+
Maybe IRB bug!
|
234
|
+
rainfall 99_998
|
235
|
+
SystemStackError: stack level too deep
|
236
|
+
from /Users/iainuser/.rvm/rubies/ruby-1.9.3-p385/lib/ruby/1.9.1/irb/workspace.rb:80
|
237
|
+
Maybe IRB bug!
|
238
|
+
rainfall 99_998
|
239
|
+
# => 49693
|
240
|
+
</code></pre>
|
241
|
+
|
242
|
+
<p>Just to be clear, I ran this with Ruby 2.0.0-rc2 as well with the same results. It's a pity that Ruby fails at this kind of thing, because it is such an elegant and useful language that seems to have borrowed the best of many other niche languages. Recursion is often the most elegant <em>and</em> performant solution.</p>
|
243
|
+
EXPECTED
|
244
|
+
}
|
245
|
+
before :all do
|
246
|
+
TextTube.load_all_filters
|
247
|
+
class MyFilter < TextTube::Base
|
248
|
+
register TextTube::LinkReffing
|
249
|
+
register TextTube::EmbeddingAudio
|
250
|
+
register TextTube::EmbeddingVideo
|
251
|
+
register do
|
252
|
+
filter_with :rdiscount do |text|
|
253
|
+
RDiscount.new(text).to_html
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
describe "With options" do
|
259
|
+
context "passed to filter" do
|
260
|
+
subject { MyFilter.new(content).filter :embeddingvideo, :embeddingaudio, :linkreffing, :rdiscount, :linkreffing => {kind: :none} }
|
261
|
+
it { should == expected }
|
262
|
+
end
|
263
|
+
context "set on the instance" do
|
264
|
+
subject { MyFilter.new(content, :linkreffing => {kind: :none}).filter :embeddingvideo, :embeddingaudio, :linkreffing, :rdiscount }
|
265
|
+
it { should == expected }
|
266
|
+
end
|
267
|
+
context "set on the class" do
|
268
|
+
before :all do
|
269
|
+
MyFilter.options.merge! :linkreffing => {kind: :none}
|
270
|
+
end
|
271
|
+
|
272
|
+
subject {
|
273
|
+
MyFilter.new(content).filter :embeddingvideo, :embeddingaudio, :linkreffing, :rdiscount }
|
274
|
+
it { should == expected }
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|