dunmanifestin 1.1.3 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e08fd19462f956e116b9fc58b7a00e8988afcc391947b2321a925249c2602458
4
- data.tar.gz: 344b6336a1c3303dd8f4ffc88cc82e37c107e34db95f89b67fbd66fd546704f5
3
+ metadata.gz: fe034e91906b9ceaa0c86e037a01edfb69ad6c737ab9fdbb626becd610bc234b
4
+ data.tar.gz: 820efff91dd927269b89fee2462747d303870b97b3648957c20c524768da0b30
5
5
  SHA512:
6
- metadata.gz: eaf0fa4b3433ed699741da6b557071d33b576c142899c402181f7b5cdf219fa619f693243f043019018aa05e8ee118fe97f065b76c0df192b1e4ca49254039d1
7
- data.tar.gz: 47281b79a2d37d99144ea58b90a50730ccb97a15274a66bf5dcb8b150cc637ab5f3a279158174027389b1e3c3f3a2346f5f0d062df4012be7cae6e2ad9233f6c
6
+ metadata.gz: 0a0bfbe9e373a9ae7730a5d1db22bd6b4fbbe46e4fe69a9cdaefe7e15b70f913d12c4bf45ae9dc51b5575ddb0c1ebe61e9bddf8aaf3346d67de380807be6f006
7
+ data.tar.gz: 40ee4e7f6a31d3310af75923e9dd5d34fbad1698bbe5703801de62189d07236886d8ad5c60c0de7181fd305b03010d096640068387787837b415097ea9e519c8
@@ -12,8 +12,6 @@ user_demands = Optimist::options do
12
12
  opt :phrase, "Specify a phrase or list, e.g. 'The [animal] sat on the [article]' or '[weapon]'", type: :string, short: '-p'
13
13
  opt :chomp, "remove the trailing newline from the output", short: '-o'
14
14
  opt :file, "Read a file as the phrase", type: :string, short: '-f'
15
- opt :coarse_seed, "Set this number to encourage phrases to resolve somewhat predictably", type: :integer, short: "-s"
16
- opt :fine_seed, "Set this number (alongside -s) to lock phrases into resolving completely predictably", type: :integer, short: "-e"
17
15
  end
18
16
 
19
17
  begin
@@ -7,5 +7,4 @@ require_relative 'dunmanifestin/string'
7
7
  require_relative 'dunmanifestin/custom_inflections'
8
8
  require_relative 'dunmanifestin/phrase'
9
9
  require_relative 'dunmanifestin/manifestation'
10
- require_relative 'dunmanifestin/list_loader'
11
10
  require_relative 'dunmanifestin/terminator'
@@ -1,30 +1,9 @@
1
- require_relative 'integer'
2
-
3
1
  class Array
4
-
5
-
6
- class << self
7
- attr_accessor :coarse_seed, :fine_seed, :diversity, :recurrences
8
-
9
- def meta_random
10
- @meta_random ||= @fine_seed ? Random.new(@fine_seed) : Random.new
11
- end
12
-
13
- def randoms
14
- @coarse_seed ||= meta_random.rand(Integer::MAX)
15
- @recurrences ||= 500
16
- @randoms ||= @recurrences.times.map do |i|
17
- Random.new(@coarse_seed + (i % (@diversity||Integer::MAX)))
18
- end
19
- end
2
+ def even_elements
3
+ select.each_with_index { |_, i| i.even? }
20
4
  end
21
5
 
22
- def constrained_sample(randoms: Array.randoms, meta_random: Array.meta_random)
23
- # $count ||= 1
24
- # p $count += 1
25
- self.sample(
26
- 1,
27
- random: randoms.sample(1, random: meta_random).pop
28
- ).pop
6
+ def odd_elements
7
+ select.each_with_index { |_, i| i.odd? }
29
8
  end
30
9
  end
@@ -0,0 +1,35 @@
1
+ class Churn
2
+ # A churn is a data structure that stores a set of things.
3
+ # You can randomly pick one of those things by calling its
4
+ # sample() method.
5
+ #
6
+ # The wrinkle is that the set of sampleable things is not
7
+ # closed. The churn will sometimes, at random, generate a
8
+ # totally new item. You can also explicitly request a
9
+ # novel item by calling generate(). Any new items
10
+ # generated are added to the churn and may be picked on
11
+ # future calls to sample().
12
+ #
13
+ # Control how often the churn generates new things using
14
+ # the novelty: parameter to initialize().
15
+
16
+ def initialize novelty:
17
+ @novelty = novelty
18
+ @generated = 0
19
+ @slots = {}
20
+ end
21
+
22
+ def sample
23
+ return yield if @novelty == 0
24
+ r = (rand * (@novelty + @slots.length)).floor
25
+ @slots[r] ||= yield
26
+ end
27
+
28
+ def generate
29
+ return yield if @novelty == 0
30
+ @slots[@generated] ||= yield
31
+ value = @slots[@generated]
32
+ @generated += 1
33
+ value
34
+ end
35
+ end
@@ -2,5 +2,6 @@ require 'active_support/inflector'
2
2
 
3
3
  ActiveSupport::Inflector.inflections do |inflect|
4
4
  inflect.irregular 'human', 'humans'
5
+ inflect.irregular 'leaf', 'leaves'
5
6
  inflect.plural /^(.+)z$/, '\0es'
6
7
  end
@@ -0,0 +1,31 @@
1
+ class Genre
2
+ GAP_BETWEEN_PALETTES = /\n(?=\|)/
3
+
4
+ def self.from_directories paths
5
+ new palettes_from paths
6
+ end
7
+
8
+ def self.palettes_from paths
9
+ paths.flat_map do |path|
10
+ Dir[File.join(path, '**', '*.pal')].flat_map do |filename|
11
+ File.read(filename)
12
+ .split(GAP_BETWEEN_PALETTES)
13
+ .map do |textual_palette|
14
+ Palette.new(textual_palette, filename)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def initialize palette_list
21
+ self.palettes = Hash[palette_list.map { |p| [p.name, p] }]
22
+ end
23
+
24
+ def palette_named name
25
+ palettes[name] || NullPalette.new(name)
26
+ end
27
+
28
+
29
+
30
+ attr_accessor :palettes
31
+ end
@@ -1,42 +1,98 @@
1
+ require_relative './phrase'
2
+ require_relative './churn'
3
+
4
+ class NullPalette
5
+ def initialize name
6
+ @name = name
7
+ end
8
+
9
+ def name
10
+ @name
11
+ end
12
+
13
+ def sample _, _, _
14
+ "{#{@name} ??}"
15
+ end
16
+ end
17
+
1
18
  class Palette
2
- GAP_BETWEEN_LISTS = /\n(?=\|)/
3
- PALETTE_TITLE = /^\|(.*?)\n/
4
- COMMENT = /\/\/(.*?)\n/
5
- class << self
6
- def expose path
7
- File.open(path).read
8
- .split(GAP_BETWEEN_LISTS)
9
- .each &method(:expose_swatches)
10
- end
19
+ GAP_BETWEEN_LISTS = /\n(?=\|)/
20
+ PALETTE_TITLE = /^\|(.*?)\n/
21
+ COMMENT = %r{//.*$}
22
+ REPETITION_PREFIX = /^\d+@/
23
+
24
+ def initialize raw_text, filename
25
+ @raw_text = raw_text
26
+ @filename = filename
27
+ end
11
28
 
12
- def expose_swatches body
13
- body.gsub!(COMMENT, '')
14
- list_name = body.match(PALETTE_TITLE)[1].to_s
29
+ def name
30
+ return file_basename if not titled?
31
+ lines.first.sub(/\|(\w+).*$/, '\1')
32
+ end
15
33
 
16
- if list_name.empty?
17
- # This seems to support palettes without |explicitTitles,
18
- # Taking them from the filename, instead.
19
- list_name = Pathname.new(path).basename
34
+ def sample genre, inflections = [], constraints = []
35
+ if inflections.any?
36
+ # don't use the churn if there are inflections, since
37
+ # the inflected text would be cached by the churn and
38
+ # could then `recur` in places where we don't want any
39
+ # inflections.
40
+ phrases.sample.reify genre, inflections
41
+ else
42
+ if constraints.include? :recur
43
+ churn.sample { phrases.sample.reify genre }
20
44
  else
21
- # Do not include palette title as a swatch
22
- # These comments should be tests.
23
- body.gsub!(PALETTE_TITLE, '')
45
+ churn.generate { phrases.sample.reify genre }
24
46
  end
25
-
26
- # This metaprogramming is mysterious to me.
27
- qlass = declare_phrase_class list_name
28
- # Where is 'list' defined?
29
- qlass.list body
30
- rescue NoMethodError
31
47
  end
48
+ rescue NoMethodError
49
+ "{#{name} ??}"
50
+ end
51
+
32
52
 
33
- def declare_phrase_class list_name
34
- name = list_name.underscore.camelize
35
- qlass = "Phrase::#{name}".constantize
36
- rescue NameError
37
- # This seems to always happen.
38
- qlass = Class.new(Phrase)
39
- Phrase.const_set name, qlass
53
+
54
+ def file_basename
55
+ File.basename(@filename, '.pal')
56
+ end
57
+
58
+ def churn
59
+ @churn ||= Churn.new novelty: novelty
60
+ end
61
+
62
+ def novelty
63
+ lines.first.sub(/^.*\*(\d+).*$/, '\1').to_i
64
+ end
65
+
66
+ def phrases
67
+ @phrases ||= begin
68
+ lines[valid_phrase_range]
69
+ .map { |line| line.sub(COMMENT, '') }
70
+ .map(&:strip)
71
+ .reject(&:empty?)
72
+ .flat_map { |line|
73
+ if line =~ REPETITION_PREFIX
74
+ [line.sub(REPETITION_PREFIX, '')] * line.to_i
75
+ else
76
+ [line]
77
+ end
78
+ }
79
+ .map(&Phrase.method(:new))
40
80
  end
41
81
  end
82
+
83
+ def valid_phrase_range
84
+ titled? ? 1..-1 : 0..-1
85
+ end
86
+
87
+ def lines
88
+ @lines ||= text.gsub(/>>(.+?)<</m, '').split("\n") | text.scan(/>>(.+?)<</m).flatten
89
+ end
90
+
91
+ def text
92
+ @text ||= @raw_text.strip
93
+ end
94
+
95
+ def titled?
96
+ lines[0][0] == '|'
97
+ end
42
98
  end
@@ -2,175 +2,115 @@ require 'active_support/inflector'
2
2
  require_relative 'custom_inflections'
3
3
  require_relative 'array'
4
4
 
5
- class Phrase
6
- def self.list new_list = nil, multiline_document = false
7
- return (@list || List.new) unless new_list
8
-
9
- new_list = new_list.split_on_newlines_and_strip if new_list.is_a?(String) unless multiline_document
10
- new_list = [new_list] if multiline_document
11
-
12
- new_list.map! do |line|
13
- multiplier_regex = /^\d+@/
14
- multiplier = line.match(multiplier_regex).to_s.to_i
15
- multiplier = 1 if multiplier < 1
16
- [line.gsub(multiplier_regex, '')] * multiplier
17
- end.flatten!.reject! { |i| i.nil? || i.empty? }
5
+ class NullPhrase
6
+ def initialize dsl_string
7
+ @dsl_string = dsl_string
8
+ end
18
9
 
19
- @list = new_list
10
+ def reify _, _
11
+ @dsl_string
20
12
  end
13
+ end
21
14
 
22
- def initialize dsl_string = self.class.list.constrained_sample
15
+ class Phrase
16
+ def initialize dsl_string
23
17
  raise "Try again." unless dsl_string
24
- compile parse dsl_string
18
+ @dsl_string = dsl_string
25
19
  end
26
20
 
27
- def compile parsed_dsl
28
- template = parsed_dsl[:template]
29
-
30
- @variable_classes = []
31
- @inflection_delegates = {
32
- :plural => [],
33
- :possessive => [],
34
- :article => [],
35
- :capitalize => [],
21
+ def reify genre, requested_inflections = []
22
+ vals = variables.map { |variable|
23
+ variable.reify genre, requested_inflections
36
24
  }
25
+ inflect requested_inflections, constant_segments.zip(vals).flatten.join('')
26
+ end
37
27
 
38
- inflections = []
39
-
40
- parsed_dsl[:variables].each_with_index do |variable, i|
41
- rough_var_class = variable[:rough_variable_class]
28
+ private
42
29
 
43
- variable[:inflections_to_delegate].each do |inflection|
44
- @inflection_delegates[inflection.to_sym] << i
45
- end
30
+ def variables
31
+ parsed_dsl[:variables]
32
+ end
46
33
 
47
- inflections[i] = []
34
+ def constant_segments
35
+ parsed_dsl[:constant_segments]
36
+ end
48
37
 
49
- variable[:inflections_to_apply].each do |inflection|
50
- inflections[i] << inflection.to_sym
51
- end
38
+ def parsed_dsl
39
+ @parsed_dsl ||= begin
40
+ tokens = @dsl_string.split(/[\[\]]/)
41
+ constant_segments = tokens.even_elements
42
+ variables = tokens.odd_elements
52
43
 
53
- begin
54
- @variable_classes << "Phrase::#{rough_var_class.camelize}".constantize
55
- rescue NameError
56
- @variable_classes << empty_phrase_class(rough_var_class)
57
- end
44
+ {
45
+ :variables => variables.map(&Variable.method(:new)),
46
+ :constant_segments => constant_segments
47
+ }
58
48
  end
59
-
60
- @to_s_proc = -> {
61
- self.variables.each_with_index do |variable, i|
62
- inflections[i].each { |inflection| variable.inflect inflection }
63
- end
64
- template.zip(self.variables).flatten.map(&:to_s).join('')
65
- }
66
49
  end
67
50
 
68
- def parse dsl_string = @dsl_string
69
- # A dsl string like "[adjective] [noun.possessive#plural]" will be parsed into
70
- # { :variables =>
71
- # [ { :rough_variable_class => 'adjective',
72
- # :inflections_to_delegate => [],
73
- # :inflections_to_apply => []
74
- # },
75
- # { :rough_variable_class => 'noun',
76
- # :inflections_to_delegate => [:plural],
77
- # :inflections_to_apply => [:possessive]
78
- # }
79
- # ],
80
- # :template => ["", " "]
81
- # }
82
- #
83
- tokens = dsl_string.split(/[\[\]]/)
84
- template = []; variables = [];
85
-
86
- tokens.each_with_index do |token, i|
87
- if i % 2 == 0
88
- template << token
89
- else
90
- variables << token
91
- end
92
- end
51
+ def inflect inflections, string
52
+ plural = inflections.include? :plural
53
+ article = inflections.include? :article
54
+ possessive = inflections.include? :possessive
55
+ capitalize = inflections.include? :capitalize
56
+ titleize = inflections.include? :titleize
93
57
 
94
- hash = {:variables => [], :template => template}
58
+ # Good, now turn this into a stateless function.
59
+ string = string.pluralize if plural && variables.none?(&:delegated_plural?)
60
+ string = (string =~ /s$/) ? "#{string}'" : "#{string}'s" if plural && possessive && variables.none?(&:delegated_plural?)
61
+ string = "#{string}'s" if !plural && possessive && variables.none?(&:delegated_possessive?)
62
+ string = (string =~ /^[aeiou]/i) ? "an #{string}" : "a #{string}" if !plural && article && variables.none?(&:delegated_article?)
63
+ string = string[0].capitalize + string[1 .. -1] if capitalize
64
+ string = string.titleize if titleize
95
65
 
96
- variables.each_with_index do |variable, i|
97
- components = variable.split(/\b/)
98
- rough_var_class = components.shift
99
- inflections_to_delegate = []
100
- inflections_to_apply = []
66
+ string
67
+ end
68
+ end
101
69
 
102
- components.each_with_index do |v, k|
103
- inflections_to_delegate << v if components[k-1] == '#'
104
- inflections_to_apply << v if components[k-1] == '.'
70
+ class Variable
71
+ def initialize dsl_string
72
+ components = dsl_string.split(/\b/)
73
+ self.palette_name = components.shift
74
+
75
+ self.inflections_delegated_to_me = []
76
+ self.demanded_inflections = []
77
+ self.constraints = []
78
+
79
+ components.each_with_index do |v, k|
80
+ case components[k-1]
81
+ when '#'
82
+ inflections_delegated_to_me << v.to_sym
83
+ when '.'
84
+ demanded_inflections << v.to_sym
85
+ when ':'
86
+ constraints << v.to_sym
105
87
  end
106
-
107
- hash[:variables] << {
108
- :rough_variable_class => rough_var_class,
109
- :inflections_to_delegate => inflections_to_delegate,
110
- :inflections_to_apply => inflections_to_apply,
111
- }
112
88
  end
113
-
114
- hash
115
- end
116
-
117
- def variables
118
- @variables ||= @variable_classes.map(&:new)
119
89
  end
120
90
 
121
- def plural?; !!@plural end
122
- def possessive?; !!@possessive end
123
- def article?; !!@article end
124
- def capitalize?; !!@capitalize end
125
- def titleize?; !!@titleize end
126
-
127
- def titleize!
128
- delegates = @inflection_delegates[:capitalize]
129
- delegates.each { |delegate| variables[delegate].capitalize! }
91
+ def reify genre, inflections_of_parent_phrase
92
+ inherited_inflections = inflections_of_parent_phrase & inflections_delegated_to_me
93
+ inflections = demanded_inflections | inherited_inflections
94
+ genre.palette_named(palette_name).sample genre, inflections, constraints
130
95
  end
131
96
 
132
- def inflect inflection
133
- return self unless @inflection_delegates
134
- self.instance_variable_set("@#{inflection}", true)
135
- return (titleize! && self) if inflection == :titleize
136
-
137
- delegates = @inflection_delegates[inflection]
138
- delegates.each { |delegate| variables[delegate].inflect inflection }
139
- self
140
- rescue NoMethodError
141
- puts "==> Failed to inflect: .#{inflection}?"
142
- puts "==> Valid inflections are: plural, possessive, article, capitalize, titleize"
143
- self
97
+ def delegated_plural?
98
+ inflections_delegated_to_me.include? :plural
144
99
  end
145
100
 
146
- def to_s
147
- render_inflections @to_s_proc.call
101
+ def delegated_article?
102
+ inflections_delegated_to_me.include? :article
148
103
  end
149
104
 
150
- def render_inflections string
151
- # Good, now turn this into a stateless function.
152
- string = string.pluralize if plural? && @inflection_delegates[:plural].empty?
153
- string = (string =~ /s$/) ? "#{string}'" : "#{string}'s" if plural? && possessive? && @inflection_delegates[:possessive].empty?
154
- string = "#{string}'s" if !plural? && possessive? && @inflection_delegates[:possessive].empty?
155
- string = (string =~ /^[aeiou]/i) ? "an #{string}" : "a #{string}" if !plural? && article? && @inflection_delegates[:article].empty?
156
- string = string[0].capitalize + string[1 .. -1] if capitalize?
157
- string = string.titleize if titleize?
158
-
159
- string
105
+ def delegated_possessive?
106
+ inflections_delegated_to_me.include? :possessive
160
107
  end
161
108
 
162
109
  private
163
110
 
164
- def empty_phrase_class name
165
- class_definition = <<-RUBY
166
- Class.new(Phrase) do
167
- def initialize
168
- @to_s_proc = -> { "{#{name} ??}" }
169
- end
170
- end
171
- RUBY
172
-
173
- eval(class_definition)
174
- end
175
-
111
+ attr_accessor \
112
+ :demanded_inflections,
113
+ :palette_name,
114
+ :inflections_delegated_to_me,
115
+ :constraints
176
116
  end
@@ -1,41 +1,27 @@
1
+ require_relative 'genre'
1
2
  require_relative 'phrase'
2
- require_relative 'list_loader'
3
- require_relative 'string'
3
+ require_relative 'palette'
4
4
 
5
5
  class Terminator
6
- def initialize(list_loader: ListLoader, shell: Shell)
7
- @list_loader = list_loader
6
+ def initialize(shell: Shell)
8
7
  @shell = shell
9
8
  end
10
9
 
11
10
  def address demands
12
- Array.coarse_seed = demands[:coarse_seed]
13
- Array.fine_seed = demands[:fine_seed]
14
- Array.diversity = 2
15
- Array.recurrences = 20
16
- phrase_string = phrasing(demands[:phrase], demands[:file])
17
- root_phrase_class = Class.new(Phrase) { list phrase_string, !!demands[:file] }
18
- list_loader.load demands[:genre]
19
- print interactive_banner if demands[:interactive]
20
-
21
- construction_loop(
22
- root_phrase_class,
23
- (demands[:count] || 1),
24
- demands[:chomp],
25
- demands[:copy],
26
- demands[:interactive]
27
- )
11
+ self.demands = demands
12
+ print interactive_banner if interactive
13
+ construction_loop
28
14
  end
29
15
 
30
16
  private
31
- DEFAULT_ROOT_PHRASEAGE = '[root]'
32
- attr_accessor :list_loader, :shell
33
17
 
34
- def construction_loop root_phrase_class, volume, chomp, copy, interact
18
+ attr_accessor :shell, :demands
19
+
20
+ def construction_loop
35
21
  fulltext = ""
36
22
  while true
37
23
  volume.times do
38
- text = root_phrase_class.new.to_s
24
+ text = Phrase.new(phrasing).reify genre
39
25
  fulltext += "\n#{text}"
40
26
  text += "\n" unless chomp
41
27
  shell.puts text
@@ -43,13 +29,21 @@ class Terminator
43
29
 
44
30
  `echo #{fulltext.inspect} | pbcopy $1` if copy
45
31
 
46
- break unless interact
32
+ break unless interactive
47
33
  break if get_from_prompt == 'quit'
48
34
  end
49
35
  end
50
36
 
51
- def phrasing given, file
52
- given || (!!file && File.read(file)) || DEFAULT_ROOT_PHRASEAGE
37
+ def genre
38
+ @genre ||= Genre.from_directories genre_directories
39
+ end
40
+
41
+ def genre_directories
42
+ ([default_genre_path] + demanded_genres).reject(&:empty?)
43
+ end
44
+
45
+ def phrasing
46
+ demanded_phrase || demanded_file_contents || '[root]'
53
47
  end
54
48
 
55
49
  def get_from_prompt
@@ -63,6 +57,50 @@ class Terminator
63
57
  [bar, message, bar].join "\n"
64
58
  end
65
59
 
60
+ def chomp
61
+ demands[:chomp]
62
+ end
63
+
64
+ def copy
65
+ demands[:copy]
66
+ end
67
+
68
+ def volume
69
+ demands[:count] || 1
70
+ end
71
+
72
+ def interactive
73
+ demands[:interactive]
74
+ end
75
+
76
+ def demanded_genres
77
+ demands[:genre] ? demands[:genre].split(':') : []
78
+ end
79
+
80
+ def demanded_file
81
+ demands[:file]
82
+ end
83
+
84
+ def demanded_file_contents
85
+ demanded_file && File.read(demanded_file)
86
+ end
87
+
88
+ def demanded_phrase
89
+ demands[:phrase]
90
+ end
91
+
92
+ def coarse_seed
93
+ demands[:coarse_seed]
94
+ end
95
+
96
+ def fine_seed
97
+ demands[:fine_seed]
98
+ end
99
+
100
+ def default_genre_path
101
+ File.join(*%W(#{File.dirname(__FILE__)} .. .. default-genre))
102
+ end
103
+
66
104
  module Shell
67
105
  class << self
68
106
  def method_missing method, *args
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dunmanifestin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - quavmo
7
+ - gavmor
8
8
  - benchristel
9
9
  - AlexLerman
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-04-06 00:00:00.000000000 Z
13
+ date: 2019-04-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -83,7 +83,7 @@ dependencies:
83
83
  description: The point of Dunmanifestin [is] to inject chaos into humans' cliched
84
84
  ideas or, at least, let them be hunter-gatherers instead of farmers of culture.
85
85
  -- B. Christel
86
- email: quavmo@gmail.com
86
+ email: morgan.gavin@gmail.com
87
87
  executables:
88
88
  - dunmanifestin
89
89
  extensions: []
@@ -98,18 +98,14 @@ files:
98
98
  - default-genre/verb.pal
99
99
  - lib/dunmanifestin.rb
100
100
  - lib/dunmanifestin/array.rb
101
+ - lib/dunmanifestin/churn.rb
101
102
  - lib/dunmanifestin/custom_inflections.rb
102
- - lib/dunmanifestin/generator.rb
103
+ - lib/dunmanifestin/genre.rb
103
104
  - lib/dunmanifestin/integer.rb
104
- - lib/dunmanifestin/list.rb
105
- - lib/dunmanifestin/list_loader.rb
106
- - lib/dunmanifestin/manifestation.rb
107
- - lib/dunmanifestin/member.rb
108
105
  - lib/dunmanifestin/palette.rb
109
106
  - lib/dunmanifestin/phrase.rb
110
- - lib/dunmanifestin/string.rb
111
107
  - lib/dunmanifestin/terminator.rb
112
- homepage: http://github.com/quavmo/dunmanifestin
108
+ homepage: http://github.com/gavmor/dunmanifestin
113
109
  licenses:
114
110
  - MIT
115
111
  metadata: {}
@@ -1,46 +0,0 @@
1
- class Generator
2
- def self.from_file path
3
- new File.open(path).readlines.map(&:chomp).reject { |line| line.empty? }.unshift('root')
4
- end
5
-
6
- def initialize lines
7
- lines.inject do |list, line|
8
- create_or_append_list(list, line)
9
- end
10
- end
11
-
12
- def lists
13
- @lists ||= {}
14
- end
15
-
16
- def generate kind
17
- kind = kind.to_s
18
- list = lists[kind] || lists['|' + kind]
19
- return "{#{kind}?}" unless list
20
- list.sample.to_s
21
- end
22
-
23
- def manifest phrase
24
- phrase.to_s
25
- #phrase.listerpolate(self)
26
- end
27
-
28
- def method_missing slug
29
- generate slug
30
- end
31
-
32
- private
33
-
34
- def create_or_append_list list, line
35
- if line.is_name?
36
- list = List.new(name: line, universe: self)
37
- else
38
- list << line
39
- end
40
-
41
- list
42
- end
43
- end
44
-
45
- class NoSuchList < StandardError
46
- end
@@ -1,31 +0,0 @@
1
- class List
2
- attr_accessor :name
3
-
4
- def initialize opts={}
5
- @name = opts.fetch(:name, 'default')
6
- @members = opts.fetch(:members, [])
7
- @universe = opts.fetch(:universe)
8
- @universe.lists[name] = self
9
- puts members
10
- end
11
-
12
-
13
- def << rough_member
14
- pieces = rough_member.split('@')
15
-
16
- weight = pieces.length > 1 ? pieces.shift.to_i : 1
17
-
18
- attrs = {body: pieces.pop, list: self, universe: universe}
19
- attrs.merge!(frequency: pieces.pop) if pieces.any?
20
- member = Member.new(attrs)
21
-
22
- weight.times { members << member }
23
- end
24
-
25
- def sample
26
- members.sample
27
- end
28
-
29
- private
30
- attr_accessor :members, :universe
31
- end
@@ -1,20 +0,0 @@
1
- require_relative 'phrase'
2
- require_relative 'string'
3
- require_relative 'palette'
4
-
5
- class ListLoader
6
- DEFAULT_GENRE = File.join(*%W(#{File.dirname(__FILE__)} .. .. default-genre))
7
-
8
- class << self
9
- def load super_genre=''
10
- [DEFAULT_GENRE, (super_genre || '').split(":")]
11
- .flatten.compact.each(&method(:load_genre))
12
- end
13
-
14
- private
15
-
16
- def load_genre dirname
17
- Dir[File.join(dirname, '**' '*.pal')].each(&Palette.method(:expose))
18
- end
19
- end
20
- end
@@ -1,30 +0,0 @@
1
- class Manifestation
2
- attr_accessor :text
3
-
4
- def initialize desired
5
- @text = manifestation of: desired[:phrase], from: desired[:genre]
6
- end
7
-
8
- private
9
-
10
- def concatenate_lists_in genre
11
- unless system("find ./lists/#{genre}/* -exec cat {} > #{genre}.list + 2>&1")
12
- puts "There is no lists/#{genre} directory in which to find lists."
13
- raise StandardError
14
- end
15
- end
16
-
17
- def manifestation desire
18
- concatenate_lists_in(desire[:from])
19
-
20
- world = Generator.from_file "#{desire[:from]}.list"
21
-
22
- text = world.manifest desire[:of]
23
- while text.length > 500
24
- text = world.manifest desire[:of]
25
- end
26
-
27
- text
28
- end
29
- end
30
-
@@ -1,18 +0,0 @@
1
- class Member
2
- attr_reader :body, :list
3
-
4
- def initialize(opts={})
5
- @list = opts.fetch(:list)
6
- @freq = opts.fetch(:frequency, 1)
7
- @body = opts.fetch(:body)
8
- @universe = opts.fetch(:universe)
9
- end
10
-
11
- def to_s
12
- body.listerpolate(universe).to_s
13
- end
14
-
15
- private
16
-
17
- attr_reader :universe
18
- end
@@ -1,38 +0,0 @@
1
- # encoding: utf-8
2
-
3
- class String
4
- def is_name?
5
- self[0] == '|'
6
- end
7
-
8
- def listerpolate universe
9
- body = self
10
-
11
- while body.match(/\[\w+\]/) do
12
- slug = body.match(/\[\w+\]/).to_s
13
- phrase = universe.send(slug.gsub('[', '').gsub(']', ''))
14
- body = body.sub(slug, phrase)
15
- end
16
-
17
- body
18
- end
19
-
20
- alias :original_capitalize :capitalize
21
-
22
- def capitalize
23
- case_mapping = {
24
- "ä" => "Ä",
25
- "ö" => "Ö",
26
- }
27
-
28
- s = original_capitalize
29
- case_mapping.each_pair do |lower, upper|
30
- s.gsub!(%r{^#{lower}}, upper)
31
- end
32
- s
33
- end
34
-
35
- def split_on_newlines_and_strip
36
- split(/\s*\n\s*/).reject(&:empty?)
37
- end
38
- end