dunmanifestin 0.0.2 → 0.0.3
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 +4 -4
- data/bin/dunmanifestin +4 -32
- data/lib/dunmanifestin/list_loader.rb +34 -36
- data/lib/dunmanifestin/phrase.rb +35 -34
- data/lib/dunmanifestin/terminator.rb +68 -0
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a03c9a49c939ede783019bf96c30c78ecc8da467
|
4
|
+
data.tar.gz: 94c48fa2ccfce6eb50e4d260f8e491b914daa048
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e27e5770e85c523f3183019cb265fc3fb32fb6a5188a9808f80a4010996e3a8ab3691ad5f5207da907b4a3321afd296b24ed080379fb22d47c71c2ab162a25ea
|
7
|
+
data.tar.gz: 16f143e4be5d5c5d40f562a0911c6334377d88e8ba62f335e615440e76e792f22384e823f0d58bcd42ac8ef40c3ddf180492121f2e5135916777f4aad2efdf4c
|
data/bin/dunmanifestin
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'trollop'
|
4
|
-
require_relative '../lib/dunmanifestin'
|
4
|
+
require_relative '../lib/dunmanifestin/terminator'
|
5
5
|
|
6
6
|
user_demands = Trollop::options do
|
7
7
|
opt :debug, "Display errors and logging", short: '-d'
|
@@ -9,41 +9,13 @@ user_demands = Trollop::options do
|
|
9
9
|
opt :count, "Specify how many lines of output to generate at once", type: :integer, short: '-n'
|
10
10
|
opt :copy, "Copies manifestation into your clipboard", short: '-c'
|
11
11
|
opt :genre, "Specify a genre, e.g. '-g scifi'", type: :string, short: '-g', default: 'default'
|
12
|
-
opt :phrase, "Specify a phrase or list, e.g. 'The [animal] sat on the [article]' or '[weapon]'", type: :string, short: '-p'
|
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: '-h'
|
14
|
-
|
15
|
-
|
16
|
-
def get_from_prompt
|
17
|
-
print "dunmanifestin > "
|
18
|
-
gets.chomp
|
19
|
-
end
|
20
|
-
|
21
|
-
def print_interactive_banner
|
22
|
-
print "---------------------------------------------------------------------\n"+
|
23
|
-
"Type 'quit' to exit the prompt. Press return to generate more output.\n"+
|
24
|
-
"---------------------------------------------------------------------\n\n"
|
14
|
+
opt :file, "Read a file as the phrase", type: :string, short: '-f'
|
25
15
|
end
|
26
16
|
|
27
17
|
begin
|
28
|
-
|
29
|
-
ListLoader.new(user_demands[:genre]).load
|
30
|
-
|
31
|
-
print_interactive_banner if user_demands[:interactive]
|
32
|
-
|
33
|
-
fulltext = ""
|
34
|
-
|
35
|
-
while true
|
36
|
-
(user_demands[:count] || 1).times do
|
37
|
-
text = root_phrase_class.new.to_s
|
38
|
-
fulltext += "\n#{text}"
|
39
|
-
text += "\n" unless user_demands[:chomp]
|
40
|
-
puts text
|
41
|
-
end
|
42
|
-
|
43
|
-
`echo #{fulltext.inspect} | pbcopy $1` if user_demands[:copy]
|
44
|
-
|
45
|
-
break if !user_demands[:interactive] || get_from_prompt == 'quit'
|
46
|
-
end
|
18
|
+
Terminator.new.address user_demands
|
47
19
|
rescue => e
|
48
20
|
raise e if user_demands[:debug]
|
49
21
|
ensure
|
@@ -1,44 +1,42 @@
|
|
1
1
|
class ListLoader
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
Dir[list_dir('default')].each(&method(:create_list_from))
|
8
|
-
Dir[list_dir(genre)].each(&method(:create_list_from)) unless genre == 'default'
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def list_dir(genre)
|
14
|
-
dir_of_this_file = File.dirname(__FILE__)
|
15
|
-
File.join(*%W(#{dir_of_this_file} .. .. lists #{genre} ** *))
|
16
|
-
end
|
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 = /\/.+$/
|
2
|
+
class << self
|
3
|
+
def load genre=@genre
|
4
|
+
Dir[list_dir('default')].each(&method(:create_list_from))
|
5
|
+
Dir[list_dir(genre)].each(&method(:create_list_from)) unless genre == 'default'
|
6
|
+
end
|
22
7
|
|
23
|
-
|
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
|
8
|
+
private
|
26
9
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
10
|
+
def list_dir(genre)
|
11
|
+
dir_of_this_file = File.dirname(__FILE__)
|
12
|
+
File.join(*%W(#{dir_of_this_file} .. .. lists #{genre} ** *))
|
13
|
+
end
|
32
14
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
15
|
+
def create_list_from path
|
16
|
+
newlines_before_a_pipe = /\n(?=\|)/
|
17
|
+
everything_up_to_the_first_newline_if_first_character_is_a_pipe = /^\|(.*?)\n/
|
18
|
+
everything_after_the_last_slash = /\/.+$/
|
19
|
+
|
20
|
+
lists = File.open(path).read.split(newlines_before_a_pipe)
|
21
|
+
lists.each_with_index do |_list, i|
|
22
|
+
list_name = _list.match(everything_up_to_the_first_newline_if_first_character_is_a_pipe)[1].to_s
|
23
|
+
|
24
|
+
if list_name.empty?
|
25
|
+
list_name = path.match(everything_after_the_last_slash).to_s
|
26
|
+
else
|
27
|
+
_list.gsub!(everything_up_to_the_first_newline_if_first_character_is_a_pipe, '')
|
28
|
+
end
|
29
|
+
|
30
|
+
phrase_class_name = list_name.underscore.camelize
|
31
|
+
begin
|
32
|
+
qlass = "Phrase::#{phrase_class_name}".constantize
|
33
|
+
rescue NameError
|
34
|
+
qlass = Class.new(Phrase)
|
35
|
+
Phrase.const_set phrase_class_name, qlass
|
36
|
+
end
|
37
|
+
|
38
|
+
qlass.list(_list)
|
39
39
|
end
|
40
|
-
|
41
|
-
qlass.list(_list)
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
data/lib/dunmanifestin/phrase.rb
CHANGED
@@ -2,29 +2,30 @@ require 'active_support/inflector'
|
|
2
2
|
|
3
3
|
class Phrase
|
4
4
|
def self.list new_list = nil
|
5
|
-
return @list unless new_list
|
6
|
-
|
5
|
+
return (@list || []) unless new_list
|
6
|
+
|
7
7
|
if new_list.is_a? String
|
8
8
|
new_list = new_list.split_on_newlines_and_strip
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
new_list.map! do |line|
|
12
12
|
multiplier_regex = /^\d+@/
|
13
13
|
multiplier = line.match(multiplier_regex).to_s.to_i
|
14
14
|
multiplier = 1 if multiplier < 1
|
15
15
|
[line.gsub(multiplier_regex, '')] * multiplier
|
16
16
|
end.flatten!.reject! { |i| i.nil? || i.empty? }
|
17
|
-
|
17
|
+
|
18
18
|
@list = new_list
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def initialize dsl_string = self.class.list.sample
|
22
|
+
raise "Try again." unless dsl_string
|
22
23
|
compile parse dsl_string
|
23
24
|
end
|
24
|
-
|
25
|
+
|
25
26
|
def compile parsed_dsl
|
26
27
|
template = parsed_dsl[:template]
|
27
|
-
|
28
|
+
|
28
29
|
@variable_classes = []
|
29
30
|
@inflection_delegates = {
|
30
31
|
:plural => [],
|
@@ -32,22 +33,22 @@ class Phrase
|
|
32
33
|
:article => [],
|
33
34
|
:capitalize => [],
|
34
35
|
}
|
35
|
-
|
36
|
+
|
36
37
|
inflections = []
|
37
|
-
|
38
|
+
|
38
39
|
parsed_dsl[:variables].each_with_index do |variable, i|
|
39
40
|
rough_var_class = variable[:rough_variable_class]
|
40
|
-
|
41
|
+
|
41
42
|
variable[:inflections_to_delegate].each do |inflection|
|
42
43
|
@inflection_delegates[inflection.to_sym] << i
|
43
44
|
end
|
44
|
-
|
45
|
+
|
45
46
|
inflections[i] = []
|
46
|
-
|
47
|
+
|
47
48
|
variable[:inflections_to_apply].each do |inflection|
|
48
49
|
inflections[i] << inflection.to_sym
|
49
50
|
end
|
50
|
-
|
51
|
+
|
51
52
|
begin
|
52
53
|
@variable_classes << "Phrase::#{rough_var_class.camelize}".constantize
|
53
54
|
rescue NameError
|
@@ -58,7 +59,7 @@ class Phrase
|
|
58
59
|
end|)
|
59
60
|
end
|
60
61
|
end
|
61
|
-
|
62
|
+
|
62
63
|
@to_s_proc = -> {
|
63
64
|
self.variables.each_with_index do |variable, i|
|
64
65
|
inflections[i].each do |inflection|
|
@@ -68,7 +69,7 @@ class Phrase
|
|
68
69
|
template.zip(self.variables).flatten.map(&:to_s).join('')
|
69
70
|
}
|
70
71
|
end
|
71
|
-
|
72
|
+
|
72
73
|
def parse dsl_string = @dsl_string
|
73
74
|
# A dsl string like "[adjective] [noun.possessive#plural]" will be parsed into
|
74
75
|
# { :variables =>
|
@@ -86,7 +87,7 @@ class Phrase
|
|
86
87
|
#
|
87
88
|
tokens = dsl_string.split(/[\[\]]/)
|
88
89
|
template = []; variables = [];
|
89
|
-
|
90
|
+
|
90
91
|
tokens.each_with_index do |token, i|
|
91
92
|
if i % 2 == 0
|
92
93
|
template << token
|
@@ -94,69 +95,69 @@ class Phrase
|
|
94
95
|
variables << token
|
95
96
|
end
|
96
97
|
end
|
97
|
-
|
98
|
+
|
98
99
|
hash = {:variables => [], :template => template}
|
99
|
-
|
100
|
+
|
100
101
|
variables.each_with_index do |variable, i|
|
101
102
|
components = variable.split(/\b/)
|
102
103
|
rough_var_class = components.shift
|
103
104
|
inflections_to_delegate = []
|
104
105
|
inflections_to_apply = []
|
105
|
-
|
106
|
+
|
106
107
|
components.each_with_index do |v, k|
|
107
108
|
inflections_to_delegate << v if components[k-1] == '#'
|
108
109
|
inflections_to_apply << v if components[k-1] == '.'
|
109
110
|
end
|
110
|
-
|
111
|
+
|
111
112
|
hash[:variables] << {
|
112
113
|
:rough_variable_class => rough_var_class,
|
113
114
|
:inflections_to_delegate => inflections_to_delegate,
|
114
115
|
:inflections_to_apply => inflections_to_apply,
|
115
116
|
}
|
116
117
|
end
|
117
|
-
|
118
|
+
|
118
119
|
hash
|
119
120
|
end
|
120
|
-
|
121
|
+
|
121
122
|
def variables
|
122
123
|
@variables ||= @variable_classes.map(&:new)
|
123
124
|
end
|
124
|
-
|
125
|
+
|
125
126
|
def plural?; !!@plural end
|
126
127
|
def possessive?; !!@possessive end
|
127
128
|
def article?; !!@article end
|
128
129
|
def capitalize?; !!@capitalize end
|
129
|
-
|
130
|
+
|
130
131
|
def plural!
|
131
132
|
@plural = true
|
132
|
-
|
133
|
+
|
133
134
|
@inflection_delegates[:plural].each do |delegate|
|
134
135
|
variables[delegate].plural!
|
135
136
|
end
|
136
137
|
self
|
137
138
|
end
|
138
|
-
|
139
|
+
|
139
140
|
def article!
|
140
141
|
@article = true
|
141
|
-
|
142
|
+
|
142
143
|
@inflection_delegates[:article].each do |delegate|
|
143
144
|
variables[delegate].article!
|
144
145
|
end
|
145
146
|
self
|
146
147
|
end
|
147
|
-
|
148
|
+
|
148
149
|
def possessive!
|
149
150
|
@possessive = true
|
150
|
-
|
151
|
+
|
151
152
|
@inflection_delegates[:possessive].each do |delegate|
|
152
153
|
variables[delegate].possessive!
|
153
154
|
end
|
154
155
|
self
|
155
156
|
end
|
156
|
-
|
157
|
+
|
157
158
|
def capitalize!
|
158
159
|
@capitalize = true
|
159
|
-
|
160
|
+
|
160
161
|
@inflection_delegates[:capitalize].each do |delegate|
|
161
162
|
variables[delegate].capitalize!
|
162
163
|
end
|
@@ -166,7 +167,7 @@ class Phrase
|
|
166
167
|
def to_s
|
167
168
|
render_inflections @to_s_proc.call
|
168
169
|
end
|
169
|
-
|
170
|
+
|
170
171
|
def render_inflections string
|
171
172
|
if plural?
|
172
173
|
string = string.pluralize if @inflection_delegates[:plural].empty?
|
@@ -190,9 +191,9 @@ class Phrase
|
|
190
191
|
string = "#{string}'s"
|
191
192
|
end
|
192
193
|
end
|
193
|
-
|
194
|
+
|
194
195
|
string = string[0].capitalize + string[1 .. -1] if capitalize?
|
195
|
-
|
196
|
+
|
196
197
|
string
|
197
198
|
end
|
198
199
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative 'phrase'
|
2
|
+
require_relative 'list_loader'
|
3
|
+
require_relative 'string'
|
4
|
+
|
5
|
+
class Terminator
|
6
|
+
def initialize(list_loader: ListLoader, shell: Shell)
|
7
|
+
@list_loader = list_loader
|
8
|
+
@shell = shell
|
9
|
+
end
|
10
|
+
|
11
|
+
def address demands
|
12
|
+
phrase_string = phrasing(demands[:phrase], demands[:file])
|
13
|
+
root_phrase_class = Class.new(Phrase) { list phrase_string }
|
14
|
+
list_loader.load demands[:genre]
|
15
|
+
print interactive_banner if demands[:interactive]
|
16
|
+
|
17
|
+
construction_loop(
|
18
|
+
root_phrase_class,
|
19
|
+
(demands[:count] || 1),
|
20
|
+
demands[:chomp],
|
21
|
+
demands[:copy],
|
22
|
+
demands[:interactive]
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
attr_accessor :list_loader, :shell
|
28
|
+
|
29
|
+
def construction_loop root_phrase_class, volume, chomp, copy, interact
|
30
|
+
fulltext = ""
|
31
|
+
while true
|
32
|
+
volume.times do
|
33
|
+
text = root_phrase_class.new.to_s
|
34
|
+
fulltext += "\n#{text}"
|
35
|
+
text += "\n" unless chomp
|
36
|
+
shell.puts text
|
37
|
+
end
|
38
|
+
|
39
|
+
`echo #{fulltext.inspect} | pbcopy $1` if copy
|
40
|
+
|
41
|
+
break unless interact
|
42
|
+
break if get_from_prompt == 'quit'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def phrasing given, file
|
47
|
+
given || (File.read(file) if file) || '[root]'
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_from_prompt
|
51
|
+
shell.print "dunmanifestin > "
|
52
|
+
shell.gets.chomp
|
53
|
+
end
|
54
|
+
|
55
|
+
def interactive_banner
|
56
|
+
message = "Type 'quit' to exit the prompt. Press return to generate more output."
|
57
|
+
bar = "-"*message.length
|
58
|
+
[bar, message, bar].join "\n"
|
59
|
+
end
|
60
|
+
|
61
|
+
module Shell
|
62
|
+
class << self
|
63
|
+
def method_missing method, *args
|
64
|
+
send method, *args
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dunmanifestin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- quavmo
|
@@ -31,6 +31,7 @@ files:
|
|
31
31
|
- lib/dunmanifestin/member.rb
|
32
32
|
- lib/dunmanifestin/phrase.rb
|
33
33
|
- lib/dunmanifestin/string.rb
|
34
|
+
- lib/dunmanifestin/terminator.rb
|
34
35
|
- lists/default/activated
|
35
36
|
- lists/default/adverb
|
36
37
|
- lists/default/ageGroup
|