oulipo 0.2.0 → 0.3.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/Gemfile.lock +1 -1
- data/README.md +54 -35
- data/lib/oulipo/enhanced_string.rb +5 -0
- data/lib/oulipo/string_em_up.rb +3 -0
- data/lib/oulipo/string_extensions.rb +86 -0
- data/lib/oulipo.rb +10 -68
- data/oulipo.gemspec +1 -1
- data/spec/alliteration_spec.rb +13 -11
- data/spec/analysis_spec.rb +1 -2
- data/spec/chaterisms_spec.rb +10 -9
- data/spec/lipograms_spec.rb +11 -9
- data/spec/palindromes_spec.rb +6 -4
- data/spec/spec_helper.rb +13 -1
- data/spec/substitution_spec.rb +11 -6
- data/spec/univocalisms_spec.rb +6 -4
- metadata +22 -29
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -8,7 +8,7 @@ It's still young, and very much liable to change.
|
|
8
8
|
|
9
9
|
The real [Oulipo](http://en.wikipedia.org/wiki/Oulipo) is a gathering of writers and mathmeticians who seek to create works using constrained writing techniques.
|
10
10
|
|
11
|
-
Install with `gem install oulipo
|
11
|
+
Install with `gem install oulipo` and `require 'oulipo'` as needed.
|
12
12
|
|
13
13
|
## Lipograms and Pangrams
|
14
14
|
|
@@ -40,37 +40,6 @@ sentence = 'Big fjords vex quick waltz nymph.'
|
|
40
40
|
Oulipo.pangram?(sentence) # => true
|
41
41
|
```
|
42
42
|
|
43
|
-
## N+7
|
44
|
-
|
45
|
-
In N+7 (sometimes known as S+7), each noun in a text is replaced with the noun seven entries after it in a dictionary.
|
46
|
-
|
47
|
-
```ruby
|
48
|
-
dictionary = Oulipo::WordList.load('big_list_of_nouns.txt')
|
49
|
-
|
50
|
-
play = <<-SHAKESPEARE
|
51
|
-
|
52
|
-
What, jealous Oberon! Fairies, skip hence:
|
53
|
-
I have forsworn his bed and company.
|
54
|
-
|
55
|
-
SHAKESPEARE
|
56
|
-
|
57
|
-
Oulipo.n_plus(7, play, dictionary) # => "What, jealous Oberon! Fallacies, skulk hence:
|
58
|
-
# I have forsworn his bedroom and compensation."
|
59
|
-
|
60
|
-
```
|
61
|
-
|
62
|
-
Oulipo includes a handy `WordList` class for reading one-word-per-line dictionary files, but a dictionary can be any object that responds to `index(word)`, `length`, and `[index]`.
|
63
|
-
|
64
|
-
```ruby
|
65
|
-
dictionary = %w{ iron gild mine gold ore paint cast lily }
|
66
|
-
|
67
|
-
king_john = 'To gild refined gold, to paint the lily'
|
68
|
-
|
69
|
-
Oulipo.n_plus(1, king_john, dictionary) # => 'To mine refined ore, to cast the iron'
|
70
|
-
```
|
71
|
-
|
72
|
-
See also: Substitution.
|
73
|
-
|
74
43
|
## Univocalims
|
75
44
|
|
76
45
|
A univocalism is a poem written using only one type of vowel.
|
@@ -132,8 +101,56 @@ Normal alliteration's a little harsh, so you can give it a threshold, too.
|
|
132
101
|
phrase = 'quick queens quibble over quails'
|
133
102
|
|
134
103
|
Oulipo.alliterativity(phrase) # => 0.8 (4/5 words start with 'q')
|
135
|
-
Oulipo.
|
136
|
-
Oulipo.
|
104
|
+
Oulipo.alliteration?(phrase, :threshold => 0.7) # => true
|
105
|
+
Oulipo.alliteration?(phrase, :threshold => 0.9) # => false
|
106
|
+
```
|
107
|
+
|
108
|
+
## N+7
|
109
|
+
|
110
|
+
In N+7 (sometimes known as S+7), each noun in a text is replaced with the noun seven entries after it in a dictionary.
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
dictionary = Oulipo::WordList.load('big_list_of_nouns.txt')
|
114
|
+
|
115
|
+
play = <<-SHAKESPEARE
|
116
|
+
|
117
|
+
What, jealous Oberon! Fairies, skip hence:
|
118
|
+
I have forsworn his bed and company.
|
119
|
+
|
120
|
+
SHAKESPEARE
|
121
|
+
|
122
|
+
Oulipo.n_plus(7, play, dictionary) # => "What, jealous Oberon! Fallacies, skulk hence:
|
123
|
+
# I have forsworn his bedroom and compensation."
|
124
|
+
|
125
|
+
```
|
126
|
+
|
127
|
+
Oulipo includes a handy `WordList` class for reading one-word-per-line dictionary files, but a dictionary can be any object that responds to `index(word)`, `length`, and `[index]`.
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
dictionary = %w{ iron gild mine gold ore paint cast lily }
|
131
|
+
|
132
|
+
king_john = 'To gild refined gold, to paint the lily'
|
133
|
+
|
134
|
+
Oulipo.n_plus(1, king_john, dictionary) # => 'To mine refined ore, to cast the iron'
|
135
|
+
```
|
136
|
+
|
137
|
+
## Extending String
|
138
|
+
|
139
|
+
You can optionally extend `String`, if you need to.
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
require 'oulipo/string_em_up'
|
143
|
+
|
144
|
+
"Sator arepo tenet opera rotas".palindrome? # => true
|
145
|
+
"Waltz, bad nymph, for quick jigs vex!".pangram? # => true
|
146
|
+
'To gild refined gold'.n_plus(7, nouns) # ... as above
|
147
|
+
```
|
148
|
+
|
149
|
+
If you'd like to use the neat short-hand, but don't want to touch `String`, you might want to use an `EnhancedString`.
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
palindrome = Oulipo::EnhancedString.new("Sator arepo tenet opera rotas")
|
153
|
+
palindrome.lipogram? # => true
|
137
154
|
```
|
138
155
|
|
139
156
|
## Analysis
|
@@ -152,6 +169,8 @@ analysis = Oulipo::Analysis.new(line, word_sets)
|
|
152
169
|
|
153
170
|
analysis.identified(:nouns) # => ['rose', 'name']
|
154
171
|
analysis.identified(:adjectives) # => ['sweet']
|
172
|
+
|
173
|
+
analysis.deconstruction # => ["A ", ["rose", :nouns], " by any other ", ["name", :nouns], " would smell as ", ["sweet", :adjectives]]
|
155
174
|
```
|
156
175
|
|
157
176
|
## Substitution
|
@@ -167,4 +186,4 @@ substitutor.replace(:nouns).increment(1) # => "A bear by any other rose would sm
|
|
167
186
|
|
168
187
|
---
|
169
188
|
|
170
|
-
|
189
|
+
Pete Nicholls ([@Aupajo](http://twitter.com/Aupajo))
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Oulipo
|
2
|
+
module StringExtensions
|
3
|
+
ALPHABET = 'a'..'z'
|
4
|
+
VOWELS = %w{ a e i o u }
|
5
|
+
|
6
|
+
# Whether the string uses alliteration or not.
|
7
|
+
# Accepts a :threshold option for determining whether the string
|
8
|
+
# uses sufficient alliteration (see #aliterativity)
|
9
|
+
def alliteration?(options = {})
|
10
|
+
threshold = options.delete(:threshold) || 1
|
11
|
+
self.alliterativity >= threshold
|
12
|
+
end
|
13
|
+
|
14
|
+
# A score between 0 and 1 representing the level of alliteration
|
15
|
+
def alliterativity
|
16
|
+
words = self.downcase.gsub(/[^a-z\s]/, '').split
|
17
|
+
leading_letters = words.map(&:chr)
|
18
|
+
|
19
|
+
# { 'a' => 3, 'b' => 1, ... }
|
20
|
+
leading_letter_counts = leading_letters.inject({}) do |result, letter|
|
21
|
+
result[letter] ||= 0
|
22
|
+
result[letter] += 1
|
23
|
+
result
|
24
|
+
end
|
25
|
+
|
26
|
+
most_used_count = leading_letter_counts.max_by { |kv| kv.last }.pop
|
27
|
+
most_used_count.to_f / words.length
|
28
|
+
end
|
29
|
+
|
30
|
+
# The same letters backwards as forwards
|
31
|
+
def palindrome?
|
32
|
+
letter_sequence = self.downcase.gsub(/[^a-z]/, '')
|
33
|
+
letter_sequence.reverse == letter_sequence
|
34
|
+
end
|
35
|
+
|
36
|
+
# Replace the words in the word list with the word n places after it
|
37
|
+
def n_plus(places, word_list)
|
38
|
+
analysis = Analysis.new(self, :nouns => word_list)
|
39
|
+
substitutor = Substitutor.new(analysis)
|
40
|
+
substitutor.replace(:nouns).increment(places)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns true if each word is one letter larger than the previous
|
44
|
+
def snowball?
|
45
|
+
words = self.split
|
46
|
+
self.chaterism? && words.first.length < words.last.length
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns true if only one vowel is used
|
50
|
+
def univocalism?
|
51
|
+
present_letters = self.downcase.split('').uniq
|
52
|
+
(VOWELS - present_letters).length == 4
|
53
|
+
end
|
54
|
+
|
55
|
+
# Returns true if the string is a sequence of words in each of which is one letter larger than the
|
56
|
+
# previous, or each word in the sequence is one letter less than the previous
|
57
|
+
def chaterism?
|
58
|
+
words = self.gsub(/[^a-z\s]/i, '').split
|
59
|
+
|
60
|
+
# Find the direction we're traveling
|
61
|
+
flen, llen = words.first.length, words.last.length
|
62
|
+
direction = flen > llen ? :downto : :upto
|
63
|
+
|
64
|
+
# Compare the pattern of word lengths against a range-turned-array of expected word lengths
|
65
|
+
words.map(&:length) == flen.send(direction, llen).to_a
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns an array of letters that are absent
|
69
|
+
def absent_letters
|
70
|
+
present_letters = self.downcase.split('').uniq
|
71
|
+
missing_letters = ALPHABET.to_a - present_letters
|
72
|
+
missing_letters.empty? ? nil : missing_letters
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns true if all letters of the alphabet are used
|
76
|
+
def pangram?
|
77
|
+
self.absent_letters.nil?
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns true if not all of the letters of the alphabet are used
|
81
|
+
def lipogram?
|
82
|
+
!self.pangram?
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
data/lib/oulipo.rb
CHANGED
@@ -1,79 +1,21 @@
|
|
1
1
|
require 'oulipo/word_list'
|
2
|
+
require 'oulipo/string_extensions'
|
3
|
+
require 'oulipo/enhanced_string'
|
2
4
|
require 'oulipo/analysis'
|
3
5
|
require 'oulipo/substitutor'
|
4
6
|
|
5
7
|
module Oulipo
|
6
|
-
ALPHABET = 'a'..'z'
|
7
|
-
VOWELS = %w{ a e i o u }
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# A pangram uses all letters
|
16
|
-
def self.pangram?(work)
|
17
|
-
self.absent_letters(work).nil?
|
18
|
-
end
|
19
|
-
|
20
|
-
# A lipogram has missing letters
|
21
|
-
def self.lipogram?(work)
|
22
|
-
!self.pangram?(work)
|
23
|
-
end
|
24
|
-
|
25
|
-
# In a chaterism, each successive word is larger than the last or vice versa
|
26
|
-
def self.chaterism?(poem)
|
27
|
-
# Discard the punctuation, split into words
|
28
|
-
words = poem.gsub(/[^a-z\s]/i, '').split
|
29
|
-
|
30
|
-
# Find the direction we're traveling
|
31
|
-
flen, llen = words.first.length, words.last.length
|
32
|
-
direction = flen > llen ? :downto : :upto
|
33
|
-
|
34
|
-
# "The tree sings".map(&:length) # => [3, 4, 5]
|
35
|
-
# [3, 4, 5] == 3.upto(5).to_a # => true
|
36
|
-
words.map(&:length) == flen.send(direction, llen).to_a
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.univocalism?(poem)
|
40
|
-
present_letters = poem.downcase.split('').uniq
|
41
|
-
(VOWELS - present_letters).length == 4
|
42
|
-
end
|
43
|
-
|
44
|
-
def self.snowball?(poem)
|
45
|
-
words = poem.split
|
46
|
-
self.chaterism?(poem) && words.first.length < words.last.length
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.palindrome?(phrase)
|
50
|
-
sequence = phrase.downcase.gsub(/[^a-z]/, '')
|
51
|
-
sequence.reverse == sequence
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.alliteration?(phrase, options = {})
|
55
|
-
threshold = options.delete(:threshold) || 1
|
56
|
-
self.alliterativity(phrase) >= threshold
|
57
|
-
end
|
58
|
-
|
59
|
-
# Calculate an alliteration score
|
60
|
-
def self.alliterativity(phrase)
|
61
|
-
words = phrase.downcase.gsub(/[^a-z\s]/, '').split
|
62
|
-
leading_letters = words.map(&:chr)
|
63
|
-
|
64
|
-
leading_letter_counts = leading_letters.inject({}) do |result, letter|
|
65
|
-
result[letter] ||= 0
|
66
|
-
result[letter] += 1
|
67
|
-
result
|
68
|
-
end
|
69
|
-
|
70
|
-
most_used_count = leading_letter_counts.max_by { |kv| kv.last }.pop
|
71
|
-
most_used_count.to_f / words.length
|
9
|
+
[:absent_letters, :pangram?, :lipogram?, :chaterism?,
|
10
|
+
:univocalism?, :snowball?, :palindrome?, :alliteration?,
|
11
|
+
:alliterativity].each do |method|
|
12
|
+
define_singleton_method(method.to_sym) do |*args|
|
13
|
+
EnhancedString.new(args.shift).send(method.to_sym, *args)
|
14
|
+
end
|
72
15
|
end
|
73
16
|
|
17
|
+
# Replace the word nth places ahead in the word_list
|
74
18
|
def self.n_plus(places, text, word_list)
|
75
|
-
|
76
|
-
substitutor = Substitutor.new(analysis)
|
77
|
-
substitutor.replace(:nouns).increment(places)
|
19
|
+
EnhancedString.new(text).n_plus(places, word_list)
|
78
20
|
end
|
79
21
|
end
|
data/oulipo.gemspec
CHANGED
data/spec/alliteration_spec.rb
CHANGED
@@ -1,26 +1,28 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'oulipo/string_em_up'
|
2
3
|
|
3
4
|
describe "alliteration" do
|
4
5
|
|
5
|
-
let(:performer) { Oulipo }
|
6
|
-
|
7
6
|
let(:pure_alliteration) { 'spec step succeeds speedily' }
|
8
7
|
let(:mostly_alliterative) { 'quick queens quibble over quails' }
|
9
8
|
|
10
9
|
it "detects pure alliteration" do
|
11
|
-
|
10
|
+
pure_alliteration.should be_alliteration
|
12
11
|
end
|
13
|
-
|
12
|
+
|
14
13
|
it "tells us the alliterativity of a phrase" do
|
15
|
-
|
16
|
-
|
14
|
+
pure_alliteration.alliterativity.should == 1.0
|
15
|
+
mostly_alliterative.alliterativity.should == 0.8
|
17
16
|
end
|
18
|
-
|
17
|
+
|
19
18
|
it "detects alliteration with a threshold" do
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
mostly_alliterative.should_not be_alliteration
|
20
|
+
mostly_alliterative.should be_alliteration(:threshold => 0.7)
|
21
|
+
mostly_alliterative.should be_alliteration(:threshold => 0.8)
|
22
|
+
mostly_alliterative.should_not be_alliteration(:threshold => 0.9)
|
24
23
|
end
|
25
24
|
|
25
|
+
it "is accessible via Oulipo" do
|
26
|
+
Oulipo.should forward_to_enhanced_string(:alliterativity, :alliteration?)
|
27
|
+
end
|
26
28
|
end
|
data/spec/analysis_spec.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Oulipo::Analysis do
|
4
|
-
include Oulipo
|
5
4
|
|
6
5
|
let(:folksong) { "O'er the moor and among the heather" }
|
7
6
|
|
8
7
|
let(:word_lists) { { :nouns => %w{ moor heather },
|
9
8
|
:prepositions => %w{ among } } }
|
10
9
|
|
11
|
-
let(:analysis) { Analysis.new(folksong, word_lists) }
|
10
|
+
let(:analysis) { Oulipo::Analysis.new(folksong, word_lists) }
|
12
11
|
|
13
12
|
it "can identify words" do
|
14
13
|
analysis.identified.sort.should == %w{ among heather moor }
|
data/spec/chaterisms_spec.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'oulipo/string_em_up'
|
2
3
|
|
3
4
|
describe "chaterisms" do
|
4
5
|
|
5
|
-
# For easy switching
|
6
|
-
let(:performer) { Oulipo }
|
7
|
-
|
8
6
|
let(:snowball_poem) do
|
9
7
|
<<-POEM
|
10
8
|
The
|
@@ -33,15 +31,18 @@ describe "chaterisms" do
|
|
33
31
|
}
|
34
32
|
|
35
33
|
it "can detect both diminishing and growing chaterisms" do
|
36
|
-
|
37
|
-
|
38
|
-
|
34
|
+
snowball_poem.should be_chaterism
|
35
|
+
diminishing_poem.should be_chaterism
|
36
|
+
regular_poem.should_not be_chaterism
|
39
37
|
end
|
40
38
|
|
41
39
|
it "detects a snowball poem" do
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
snowball_poem.should be_snowball
|
41
|
+
diminishing_poem.should_not be_snowball
|
42
|
+
regular_poem.should_not be_snowball
|
45
43
|
end
|
46
44
|
|
45
|
+
it "is accessible via Oulipo" do
|
46
|
+
Oulipo.should forward_to_enhanced_string(:chaterism?, :snowball?)
|
47
|
+
end
|
47
48
|
end
|
data/spec/lipograms_spec.rb
CHANGED
@@ -1,24 +1,26 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'oulipo/string_em_up'
|
2
3
|
|
3
4
|
describe "lipograms and pangrams" do
|
4
5
|
|
5
|
-
# Easy to switch class, if refactored
|
6
|
-
let(:performer) { Oulipo }
|
7
|
-
|
8
6
|
let(:pangram) { 'The quick brown fox jumps over a lazy god' }
|
9
7
|
let(:lipogram) { 'The quick grey fox jumps over lazy gods' }
|
10
8
|
|
11
9
|
it "shows absent letters" do
|
12
|
-
|
13
|
-
|
10
|
+
pangram.absent_letters.should be_nil
|
11
|
+
lipogram.absent_letters.should == %w{ b n w }
|
14
12
|
end
|
15
13
|
|
16
14
|
it "can tell a pangram from a lipogram" do
|
17
|
-
|
18
|
-
|
15
|
+
lipogram.should be_lipogram
|
16
|
+
pangram.should_not be_lipogram
|
19
17
|
|
20
|
-
|
21
|
-
|
18
|
+
lipogram.should_not be_pangram
|
19
|
+
pangram.should be_pangram
|
20
|
+
end
|
21
|
+
|
22
|
+
it "is accessible via Oulipo" do
|
23
|
+
Oulipo.should forward_to_enhanced_string(:lipogram?, :pangram?)
|
22
24
|
end
|
23
25
|
|
24
26
|
end
|
data/spec/palindromes_spec.rb
CHANGED
@@ -2,11 +2,13 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe "palindromes" do
|
4
4
|
|
5
|
-
let(:performer) { Oulipo }
|
6
|
-
|
7
5
|
it "detects palindromes" do
|
8
|
-
|
9
|
-
|
6
|
+
'Mr. Owl ate my metal worm'.should be_palindrome
|
7
|
+
'Carelessness is a dish best served drunk'.should_not be_palindrome
|
8
|
+
end
|
9
|
+
|
10
|
+
it "is accessible via Oulipo" do
|
11
|
+
Oulipo.should forward_to_enhanced_string(:palindrome?)
|
10
12
|
end
|
11
13
|
|
12
14
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,4 +2,16 @@ require 'bundler'
|
|
2
2
|
Bundler.setup(:default, :test)
|
3
3
|
|
4
4
|
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
5
|
-
require 'oulipo'
|
5
|
+
require 'oulipo'
|
6
|
+
|
7
|
+
RSpec::Matchers.define :forward_to_enhanced_string do |*forwarded_methods|
|
8
|
+
match do |oulipo|
|
9
|
+
stubs = forwarded_methods.inject({}) { |stubs, method| stubs.merge(method => :forwarded) }
|
10
|
+
enhanced_string = mock(:enhanced_string, stubs)
|
11
|
+
Oulipo::EnhancedString.should_receive(:new).with('a phrase').at_least(:once).and_return(enhanced_string)
|
12
|
+
|
13
|
+
forwarded_methods.each do |method|
|
14
|
+
oulipo.send(method, 'a phrase').should == :forwarded
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/substitution_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'oulipo/string_em_up'
|
2
3
|
|
3
4
|
describe "substitution" do
|
4
5
|
|
@@ -10,8 +11,6 @@ describe "substitution" do
|
|
10
11
|
Oulipo::Substitutor.new analysis_with(*args)
|
11
12
|
end
|
12
13
|
|
13
|
-
let(:performer) { Oulipo }
|
14
|
-
|
15
14
|
let(:phrase) { 'The bear ate the badger' }
|
16
15
|
let(:noun_list) { %w{ badger bat bear } }
|
17
16
|
let(:substitutor) { substitutor_with(phrase, :nouns => noun_list) }
|
@@ -25,11 +24,17 @@ describe "substitution" do
|
|
25
24
|
it "raises an error if increment is called before replace" do
|
26
25
|
lambda { substitutor.increment(3) }.should raise_error
|
27
26
|
end
|
28
|
-
|
27
|
+
|
29
28
|
it "can be accessed from Oulipo with n_plus" do
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
Oulipo.n_plus(1, phrase, noun_list).should == 'The badger ate the bat'
|
30
|
+
Oulipo.n_plus(2, phrase, noun_list).should == 'The bat ate the bear'
|
31
|
+
Oulipo.n_plus(6, phrase, noun_list).should == 'The bear ate the badger'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "can be accessed from a string with n_plus" do
|
35
|
+
phrase.n_plus(1, noun_list).should == 'The badger ate the bat'
|
36
|
+
phrase.n_plus(2, noun_list).should == 'The bat ate the bear'
|
37
|
+
phrase.n_plus(6, noun_list).should == 'The bear ate the badger'
|
33
38
|
end
|
34
39
|
|
35
40
|
it "handles unused nouns" do
|
data/spec/univocalisms_spec.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'oulipo/string_em_up'
|
2
3
|
|
3
4
|
describe "univocalisms" do
|
4
5
|
|
5
|
-
let(:performer) { Oulipo }
|
6
|
-
|
7
6
|
let(:univocalism) {
|
8
7
|
<<-POEM
|
9
8
|
No cool monsoons blow soft on Oxford dons,
|
@@ -23,8 +22,11 @@ describe "univocalisms" do
|
|
23
22
|
}
|
24
23
|
|
25
24
|
it "detects a univocalism" do
|
26
|
-
|
27
|
-
|
25
|
+
univocalism.should be_univocalism
|
26
|
+
regular_poem.should_not be_univocalism
|
28
27
|
end
|
29
28
|
|
29
|
+
it "is accessible via Oulipo" do
|
30
|
+
Oulipo.should forward_to_enhanced_string(:univocalism?)
|
31
|
+
end
|
30
32
|
end
|
metadata
CHANGED
@@ -1,28 +1,22 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: oulipo
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
4
5
|
prerelease:
|
5
|
-
version: 0.2.0
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Pete Nicholls
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2011-07-29 00:00:00 +12:00
|
14
|
-
default_executable:
|
12
|
+
date: 2011-08-01 00:00:00.000000000 Z
|
15
13
|
dependencies: []
|
16
|
-
|
17
14
|
description: Oulipo gives you tools to write constrained stories and poems with Ruby.
|
18
15
|
email: pete@metanation.com
|
19
16
|
executables: []
|
20
|
-
|
21
17
|
extensions: []
|
22
|
-
|
23
18
|
extra_rdoc_files: []
|
24
|
-
|
25
|
-
files:
|
19
|
+
files:
|
26
20
|
- Gemfile
|
27
21
|
- Gemfile.lock
|
28
22
|
- LICENSE
|
@@ -30,6 +24,9 @@ files:
|
|
30
24
|
- Rakefile
|
31
25
|
- lib/oulipo.rb
|
32
26
|
- lib/oulipo/analysis.rb
|
27
|
+
- lib/oulipo/enhanced_string.rb
|
28
|
+
- lib/oulipo/string_em_up.rb
|
29
|
+
- lib/oulipo/string_extensions.rb
|
33
30
|
- lib/oulipo/substitutor.rb
|
34
31
|
- lib/oulipo/word_list.rb
|
35
32
|
- oulipo.gemspec
|
@@ -43,35 +40,31 @@ files:
|
|
43
40
|
- spec/substitution_spec.rb
|
44
41
|
- spec/univocalisms_spec.rb
|
45
42
|
- spec/word_list_spec.rb
|
46
|
-
has_rdoc: true
|
47
43
|
homepage: http://github.com/Aupajo/oulipo
|
48
44
|
licenses: []
|
49
|
-
|
50
45
|
post_install_message:
|
51
46
|
rdoc_options: []
|
52
|
-
|
53
|
-
require_paths:
|
47
|
+
require_paths:
|
54
48
|
- lib
|
55
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
50
|
none: false
|
57
|
-
requirements:
|
58
|
-
- -
|
59
|
-
- !ruby/object:Gem::Version
|
60
|
-
version:
|
61
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
56
|
none: false
|
63
|
-
requirements:
|
64
|
-
- -
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
version:
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
67
61
|
requirements: []
|
68
|
-
|
69
62
|
rubyforge_project:
|
70
|
-
rubygems_version: 1.6
|
63
|
+
rubygems_version: 1.8.6
|
71
64
|
signing_key:
|
72
65
|
specification_version: 3
|
73
66
|
summary: Constrained writing with Ruby.
|
74
|
-
test_files:
|
67
|
+
test_files:
|
75
68
|
- spec/alliteration_spec.rb
|
76
69
|
- spec/analysis_spec.rb
|
77
70
|
- spec/chaterisms_spec.rb
|