dunmanifestin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +15 -0
  2. data/bin/dunmanifestin +49 -0
  3. data/lib/dunmanifestin.rb +11 -0
  4. data/lib/dunmanifestin/custom_inflections.rb +5 -0
  5. data/lib/dunmanifestin/generator.rb +46 -0
  6. data/lib/dunmanifestin/list.rb +30 -0
  7. data/lib/dunmanifestin/list_loader.rb +46 -0
  8. data/lib/dunmanifestin/manifestation.rb +30 -0
  9. data/lib/dunmanifestin/member.rb +18 -0
  10. data/lib/dunmanifestin/phrase.rb +198 -0
  11. data/lib/dunmanifestin/string.rb +38 -0
  12. data/lists/default/activated +12 -0
  13. data/lists/default/adverb +13 -0
  14. data/lists/default/ageGroup +5 -0
  15. data/lists/default/alienName +33 -0
  16. data/lists/default/alignment +10 -0
  17. data/lists/default/animal +30 -0
  18. data/lists/default/appearance +33 -0
  19. data/lists/default/attitude +17 -0
  20. data/lists/default/bag +4 -0
  21. data/lists/default/baggage +29 -0
  22. data/lists/default/baseItem +47 -0
  23. data/lists/default/buildingType +11 -0
  24. data/lists/default/clothing +7 -0
  25. data/lists/default/color +41 -0
  26. data/lists/default/container +7 -0
  27. data/lists/default/curse +10 -0
  28. data/lists/default/denizen +3 -0
  29. data/lists/default/denizenDetail +6 -0
  30. data/lists/default/description +3 -0
  31. data/lists/default/desire +26 -0
  32. data/lists/default/disability +8 -0
  33. data/lists/default/disease +10 -0
  34. data/lists/default/economy +11 -0
  35. data/lists/default/encounter +2409 -0
  36. data/lists/default/englishName +230 -0
  37. data/lists/default/epithet +13 -0
  38. data/lists/default/facet +17 -0
  39. data/lists/default/facetOfCulture +3 -0
  40. data/lists/default/family +5 -0
  41. data/lists/default/fear +30 -0
  42. data/lists/default/finnishName +81 -0
  43. data/lists/default/foodOrDrink +19 -0
  44. data/lists/default/geologicalFormation +14 -0
  45. data/lists/default/greenlandicName +43 -0
  46. data/lists/default/grossBodyPart +8 -0
  47. data/lists/default/group +6 -0
  48. data/lists/default/hardMaterial +6 -0
  49. data/lists/default/height +4 -0
  50. data/lists/default/japaneseName +202 -0
  51. data/lists/default/jewelery +13 -0
  52. data/lists/default/koboldName +68 -0
  53. data/lists/default/latinName +40 -0
  54. data/lists/default/magicItemDescription +24 -0
  55. data/lists/default/material +3 -0
  56. data/lists/default/metal +3 -0
  57. data/lists/default/mineral +3 -0
  58. data/lists/default/monster +160 -0
  59. data/lists/default/name +86 -0
  60. data/lists/default/namePrefix +30 -0
  61. data/lists/default/nameSuffix +18 -0
  62. data/lists/default/negativeAdverb +6 -0
  63. data/lists/default/negativeQuality +19 -0
  64. data/lists/default/neutralQuality +14 -0
  65. data/lists/default/nonPreciousMetal +6 -0
  66. data/lists/default/object +5 -0
  67. data/lists/default/person +4 -0
  68. data/lists/default/personName +3 -0
  69. data/lists/default/personality +34 -0
  70. data/lists/default/place +10 -0
  71. data/lists/default/placeName +4 -0
  72. data/lists/default/placeSuffix +36 -0
  73. data/lists/default/positiveAdverb +5 -0
  74. data/lists/default/positiveQuality +12 -0
  75. data/lists/default/preciousMetal +4 -0
  76. data/lists/default/preciousStone +6 -0
  77. data/lists/default/profession +21 -0
  78. data/lists/default/province +3 -0
  79. data/lists/default/quality +4 -0
  80. data/lists/default/qualityWithAdverb +4 -0
  81. data/lists/default/race +11 -0
  82. data/lists/default/raceOrProfession +5 -0
  83. data/lists/default/reason +15 -0
  84. data/lists/default/resource +9 -0
  85. data/lists/default/root +6 -0
  86. data/lists/default/secret +9 -0
  87. data/lists/default/settlementDetail +6 -0
  88. data/lists/default/settlementType +7 -0
  89. data/lists/default/softMaterial +7 -0
  90. data/lists/default/structureDetail +8 -0
  91. data/lists/default/structureType +24 -0
  92. data/lists/default/superpower +6 -0
  93. data/lists/default/topicOfConversation +5 -0
  94. data/lists/default/weapon +149 -0
  95. data/lists/default/wearable +4 -0
  96. data/lists/default/wearableQuality +15 -0
  97. data/lists/default/weildable +10 -0
  98. data/lists/default/welshName +79 -0
  99. data/lists/huoquitlan/originalAnimal +250 -0
  100. data/lists/huoquitlan/originalDenizen +849 -0
  101. data/lists/huoquitlan/originalItemName +33 -0
  102. data/lists/huoquitlan/originalNPC +99 -0
  103. data/lists/huoquitlan/originalName +226 -0
  104. data/lists/hypotheticals/noun +373 -0
  105. data/lists/hypotheticals/root +15 -0
  106. data/lists/hypotheticals/transitiveVerb +628 -0
  107. data/lists/hypotheticals/verbs +653 -0
  108. data/lists/sophistry/root +269 -0
  109. metadata +156 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZGY3OWM3NzkwOWIwZmNjYjllYjlkMWUzMzIwOWE5ZmU2YzY5MDhkNA==
5
+ data.tar.gz: !binary |-
6
+ MmZhYjIwYWYyOWU3ZjkzYWFmMGMyN2U1YzE3NDY4NmE2N2YwZGQzYQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MDdjOGY5ODNiOTMyYzViNmIwNjUwN2RjNjViOTk4ZGQxYWEyMmQ2ZmM4NmY4
10
+ YjVlYmI0ZDRmNGRjNjBlYTdmNzU3N2Q0MmVhY2ViZmQyZjVjMDA0MmNkZDgx
11
+ MzI3MTAyODA4NWIwMTEzNDIwYmU4MzY1Zjg5NzFiYTJlNzIyYmY=
12
+ data.tar.gz: !binary |-
13
+ M2U3MWZmNjUwM2FhZWNlZjg1M2Y1M2VlZDA0MTdkNDhmMDRlNjQzNDAxM2Mx
14
+ N2EzNjg4ZTliOWEyMDQ3YzNjMTc1OWRjMDk4Yzk3NzA4NmZlNmFiNzhjMWMw
15
+ ZjI5MDJmNGM4YjU0OTc3MjEwZTc3M2VjMzA3ZDFkMDAzNjcxYWM=
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dunmanifestin'
4
+
5
+ user_demands = Trollop::options do
6
+ opt :debug, "Display errors and logging", short: '-d'
7
+ opt :interactive, "Use an interactive command prompt", short: '-i'
8
+ opt :count, "Specify how many lines of output to generate at once", type: :integer, short: '-n'
9
+ opt :copy, "Copies manifestation into your clipboard", short: '-c'
10
+ opt :genre, "Specify a genre, e.g. '-g scifi'", type: :string, short: '-g', default: 'default'
11
+ opt :phrase, "Specify a phrase or list, e.g. 'The [animal] sat on the [article]' or '[weapon]'", type: :string, short: '-p', default: '[root]'
12
+ opt :chomp, "remove the trailing newline from the output", short: '-h'
13
+ end
14
+
15
+ def get_from_prompt
16
+ print "dunmanifestin > "
17
+ gets.chomp
18
+ end
19
+
20
+ begin
21
+ root_phrase_class = Class.new(Phrase) { list user_demands[:phrase] }
22
+ ListLoader.new(user_demands[:genre]).load
23
+
24
+ if user_demands[:interactive]
25
+ print "---------------------------------------------------------------------\n"+
26
+ "Type 'quit' to exit the prompt. Press return to generate more output.\n"+
27
+ "---------------------------------------------------------------------\n\n"
28
+ end
29
+
30
+ fulltext = ""
31
+
32
+ while true
33
+ (user_demands[:count] || 1).times do
34
+ text = root_phrase_class.new.inspect
35
+ fulltext += "\n#{text}"
36
+ text += "\n" unless user_demands[:chomp]
37
+ print text
38
+ end
39
+
40
+ `echo #{fulltext.inspect} | pbcopy $1` if user_demands[:copy]
41
+
42
+ break if !user_demands[:interactive] || get_from_prompt == 'quit'
43
+ end
44
+
45
+ rescue => e
46
+ raise e if user_demands[:debug]
47
+ ensure
48
+ `rm #{user_demands[:genre]}.list 2>&1` unless user_demands[:debug]
49
+ end
@@ -0,0 +1,11 @@
1
+ $:.unshift File.dirname(__FILE__) # For dev/use when no gem is installed
2
+
3
+ require 'trollop'
4
+ require 'dunmanifestin/member.rb'
5
+ require 'dunmanifestin/list.rb'
6
+ require 'dunmanifestin/generator.rb'
7
+ require 'dunmanifestin/string.rb'
8
+ require 'dunmanifestin/custom_inflections.rb'
9
+ require 'dunmanifestin/phrase.rb'
10
+ require 'dunmanifestin/manifestation.rb'
11
+ require 'dunmanifestin/list_loader.rb'
@@ -0,0 +1,5 @@
1
+ require 'active_support/inflector'
2
+
3
+ ActiveSupport::Inflector.inflections do |inflect|
4
+ inflect.irregular 'human', 'humans'
5
+ end
@@ -0,0 +1,46 @@
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
@@ -0,0 +1,30 @@
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
+ end
10
+
11
+
12
+ def << rough_member
13
+ pieces = rough_member.split('@')
14
+
15
+ weight = pieces.length > 1 ? pieces.shift.to_i : 1
16
+
17
+ attrs = {body: pieces.pop, list: self, universe: universe}
18
+ attrs.merge!(frequency: pieces.pop) if pieces.any?
19
+ member = Member.new(attrs)
20
+
21
+ weight.times { members << member }
22
+ end
23
+
24
+ def sample
25
+ members.sample
26
+ end
27
+
28
+ private
29
+ attr_accessor :members, :universe
30
+ end
@@ -0,0 +1,46 @@
1
+ class ListLoader
2
+ def initialize genre = 'default'
3
+ @genre = genre
4
+ end
5
+
6
+ def load genre=@genre
7
+ dir_of_this_file = File.dirname(__FILE__)
8
+ default_list_dir = File.join(*%W(#{dir_of_this_file} .. .. lists default ** *))
9
+ Dir[default_list_dir].each { |list_path| create_list_from(list_path) }
10
+
11
+ if genre != 'default'
12
+ Dir[File.join(*%W(#{dir_of_this_file} .. lists #{genre} ** *))].each { |list_path| create_list_from(list_path) }
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def create_list_from path
19
+ newlines_before_a_pipe = /\n(?=\|)/
20
+ everything_up_to_the_first_newline_if_first_character_is_a_pipe = /^\|(.*?)\n/
21
+ everything_after_the_last_slash = /\/.+$/
22
+
23
+ lists = File.open(path).read.split(newlines_before_a_pipe)
24
+ lists.each_with_index do |_list, i|
25
+ list_name = _list.match(everything_up_to_the_first_newline_if_first_character_is_a_pipe)[1].to_s
26
+
27
+ if list_name.empty?
28
+ list_name = path.match(everything_after_the_last_slash).to_s
29
+ else
30
+ _list.gsub!(everything_up_to_the_first_newline_if_first_character_is_a_pipe, '')
31
+ end
32
+
33
+ phrase_class_name = list_name.underscore.camelize
34
+ begin
35
+ qlass = "Phrase::#{phrase_class_name}".constantize
36
+ rescue NameError
37
+ qlass = Class.new(Phrase)
38
+ Phrase.const_set phrase_class_name, qlass
39
+ end
40
+
41
+ qlass.list(_list)
42
+ end
43
+ end
44
+ end
45
+
46
+
@@ -0,0 +1,30 @@
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
+
@@ -0,0 +1,18 @@
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
@@ -0,0 +1,198 @@
1
+ require 'active_support/inflector'
2
+
3
+ class Phrase
4
+ def self.list new_list = nil
5
+ return @list unless new_list
6
+
7
+ if new_list.is_a? String
8
+ new_list = new_list.split_on_newlines_and_strip
9
+ end
10
+
11
+ new_list.map! do |line|
12
+ multiplier_regex = /^\d+@/
13
+ multiplier = line.match(multiplier_regex).to_s.to_i
14
+ multiplier = 1 if multiplier < 1
15
+ [line.gsub(multiplier_regex, '')] * multiplier
16
+ end.flatten!.reject! { |i| i.nil? || i.empty? }
17
+
18
+ @list = new_list
19
+ end
20
+
21
+ def initialize dsl_string = self.class.list.sample
22
+ compile parse dsl_string
23
+ end
24
+
25
+ def compile parsed_dsl
26
+ template = parsed_dsl[:template]
27
+
28
+ @variable_classes = []
29
+ @inflection_delegates = {
30
+ :plural => [],
31
+ :possessive => [],
32
+ :article => [],
33
+ :capitalize => [],
34
+ }
35
+
36
+ inflections = []
37
+
38
+ parsed_dsl[:variables].each_with_index do |variable, i|
39
+ rough_var_class = variable[:rough_variable_class]
40
+
41
+ variable[:inflections_to_delegate].each do |inflection|
42
+ @inflection_delegates[inflection.to_sym] << i
43
+ end
44
+
45
+ inflections[i] = []
46
+
47
+ variable[:inflections_to_apply].each do |inflection|
48
+ inflections[i] << inflection.to_sym
49
+ end
50
+
51
+ begin
52
+ @variable_classes << "Phrase::#{rough_var_class.camelize}".constantize
53
+ rescue NameError
54
+ @variable_classes << eval(%Q|Class.new(Phrase) do
55
+ def initialize
56
+ @to_s_proc = -> { "{#{rough_var_class} ??}" }
57
+ end
58
+ end|)
59
+ end
60
+ end
61
+
62
+ @to_s_proc = -> {
63
+ self.variables.each_with_index do |variable, i|
64
+ inflections[i].each do |inflection|
65
+ variable.send "#{inflection}!"
66
+ end
67
+ end
68
+ template.zip(self.variables).flatten.map(&:to_s).join('')
69
+ }
70
+ end
71
+
72
+ def parse dsl_string = @dsl_string
73
+ # A dsl string like "[adjective] [noun.possessive#plural]" will be parsed into
74
+ # { :variables =>
75
+ # [ { :rough_variable_class => 'adjective',
76
+ # :inflections_to_delegate => [],
77
+ # :inflections_to_apply => []
78
+ # },
79
+ # { :rough_variable_class => 'noun',
80
+ # :inflections_to_delegate => [:plural],
81
+ # :inflections_to_apply => [:possessive]
82
+ # }
83
+ # ],
84
+ # :template => ["", " "]
85
+ # }
86
+ #
87
+ tokens = dsl_string.split(/[\[\]]/)
88
+ template = []; variables = [];
89
+
90
+ tokens.each_with_index do |token, i|
91
+ if i % 2 == 0
92
+ template << token
93
+ else
94
+ variables << token
95
+ end
96
+ end
97
+
98
+ hash = {:variables => [], :template => template}
99
+
100
+ variables.each_with_index do |variable, i|
101
+ components = variable.split(/\b/)
102
+ rough_var_class = components.shift
103
+ inflections_to_delegate = []
104
+ inflections_to_apply = []
105
+
106
+ components.each_with_index do |v, k|
107
+ inflections_to_delegate << v if components[k-1] == '#'
108
+ inflections_to_apply << v if components[k-1] == '.'
109
+ end
110
+
111
+ hash[:variables] << {
112
+ :rough_variable_class => rough_var_class,
113
+ :inflections_to_delegate => inflections_to_delegate,
114
+ :inflections_to_apply => inflections_to_apply,
115
+ }
116
+ end
117
+
118
+ hash
119
+ end
120
+
121
+ def variables
122
+ @variables ||= @variable_classes.map(&:new)
123
+ end
124
+
125
+ def plural?; !!@plural end
126
+ def possessive?; !!@possessive end
127
+ def article?; !!@article end
128
+ def capitalize?; !!@capitalize end
129
+
130
+ def plural!
131
+ @plural = true
132
+
133
+ @inflection_delegates[:plural].each do |delegate|
134
+ variables[delegate].plural!
135
+ end
136
+ self
137
+ end
138
+
139
+ def article!
140
+ @article = true
141
+
142
+ @inflection_delegates[:article].each do |delegate|
143
+ variables[delegate].article!
144
+ end
145
+ self
146
+ end
147
+
148
+ def possessive!
149
+ @possessive = true
150
+
151
+ @inflection_delegates[:possessive].each do |delegate|
152
+ variables[delegate].possessive!
153
+ end
154
+ self
155
+ end
156
+
157
+ def capitalize!
158
+ @capitalize = true
159
+
160
+ @inflection_delegates[:capitalize].each do |delegate|
161
+ variables[delegate].capitalize!
162
+ end
163
+ self
164
+ end
165
+
166
+ def to_s
167
+ render_inflections @to_s_proc.call
168
+ end
169
+
170
+ def render_inflections string
171
+ if plural?
172
+ string = string.pluralize if @inflection_delegates[:plural].empty?
173
+ if possessive? && @inflection_delegates[:possessive].empty?
174
+ if string =~ /s$/
175
+ string = "#{string}'"
176
+ else
177
+ string = "#{string}'s"
178
+ end
179
+ end
180
+ else
181
+ #singular
182
+ if article? && @inflection_delegates[:article].empty?
183
+ if string =~ /^[aeiou]/i
184
+ string = "an #{string}"
185
+ else
186
+ string = "a #{string}"
187
+ end
188
+ end
189
+ if possessive? && @inflection_delegates[:possessive].empty?
190
+ string = "#{string}'s"
191
+ end
192
+ end
193
+
194
+ string = string.capitalize if capitalize?
195
+
196
+ string
197
+ end
198
+ end