dunmanifestin 1.1.3 → 1.2.0

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.
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