dunmanifestin 0.0.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.
- checksums.yaml +15 -0
- data/bin/dunmanifestin +49 -0
- data/lib/dunmanifestin.rb +11 -0
- data/lib/dunmanifestin/custom_inflections.rb +5 -0
- data/lib/dunmanifestin/generator.rb +46 -0
- data/lib/dunmanifestin/list.rb +30 -0
- data/lib/dunmanifestin/list_loader.rb +46 -0
- data/lib/dunmanifestin/manifestation.rb +30 -0
- data/lib/dunmanifestin/member.rb +18 -0
- data/lib/dunmanifestin/phrase.rb +198 -0
- data/lib/dunmanifestin/string.rb +38 -0
- data/lists/default/activated +12 -0
- data/lists/default/adverb +13 -0
- data/lists/default/ageGroup +5 -0
- data/lists/default/alienName +33 -0
- data/lists/default/alignment +10 -0
- data/lists/default/animal +30 -0
- data/lists/default/appearance +33 -0
- data/lists/default/attitude +17 -0
- data/lists/default/bag +4 -0
- data/lists/default/baggage +29 -0
- data/lists/default/baseItem +47 -0
- data/lists/default/buildingType +11 -0
- data/lists/default/clothing +7 -0
- data/lists/default/color +41 -0
- data/lists/default/container +7 -0
- data/lists/default/curse +10 -0
- data/lists/default/denizen +3 -0
- data/lists/default/denizenDetail +6 -0
- data/lists/default/description +3 -0
- data/lists/default/desire +26 -0
- data/lists/default/disability +8 -0
- data/lists/default/disease +10 -0
- data/lists/default/economy +11 -0
- data/lists/default/encounter +2409 -0
- data/lists/default/englishName +230 -0
- data/lists/default/epithet +13 -0
- data/lists/default/facet +17 -0
- data/lists/default/facetOfCulture +3 -0
- data/lists/default/family +5 -0
- data/lists/default/fear +30 -0
- data/lists/default/finnishName +81 -0
- data/lists/default/foodOrDrink +19 -0
- data/lists/default/geologicalFormation +14 -0
- data/lists/default/greenlandicName +43 -0
- data/lists/default/grossBodyPart +8 -0
- data/lists/default/group +6 -0
- data/lists/default/hardMaterial +6 -0
- data/lists/default/height +4 -0
- data/lists/default/japaneseName +202 -0
- data/lists/default/jewelery +13 -0
- data/lists/default/koboldName +68 -0
- data/lists/default/latinName +40 -0
- data/lists/default/magicItemDescription +24 -0
- data/lists/default/material +3 -0
- data/lists/default/metal +3 -0
- data/lists/default/mineral +3 -0
- data/lists/default/monster +160 -0
- data/lists/default/name +86 -0
- data/lists/default/namePrefix +30 -0
- data/lists/default/nameSuffix +18 -0
- data/lists/default/negativeAdverb +6 -0
- data/lists/default/negativeQuality +19 -0
- data/lists/default/neutralQuality +14 -0
- data/lists/default/nonPreciousMetal +6 -0
- data/lists/default/object +5 -0
- data/lists/default/person +4 -0
- data/lists/default/personName +3 -0
- data/lists/default/personality +34 -0
- data/lists/default/place +10 -0
- data/lists/default/placeName +4 -0
- data/lists/default/placeSuffix +36 -0
- data/lists/default/positiveAdverb +5 -0
- data/lists/default/positiveQuality +12 -0
- data/lists/default/preciousMetal +4 -0
- data/lists/default/preciousStone +6 -0
- data/lists/default/profession +21 -0
- data/lists/default/province +3 -0
- data/lists/default/quality +4 -0
- data/lists/default/qualityWithAdverb +4 -0
- data/lists/default/race +11 -0
- data/lists/default/raceOrProfession +5 -0
- data/lists/default/reason +15 -0
- data/lists/default/resource +9 -0
- data/lists/default/root +6 -0
- data/lists/default/secret +9 -0
- data/lists/default/settlementDetail +6 -0
- data/lists/default/settlementType +7 -0
- data/lists/default/softMaterial +7 -0
- data/lists/default/structureDetail +8 -0
- data/lists/default/structureType +24 -0
- data/lists/default/superpower +6 -0
- data/lists/default/topicOfConversation +5 -0
- data/lists/default/weapon +149 -0
- data/lists/default/wearable +4 -0
- data/lists/default/wearableQuality +15 -0
- data/lists/default/weildable +10 -0
- data/lists/default/welshName +79 -0
- data/lists/huoquitlan/originalAnimal +250 -0
- data/lists/huoquitlan/originalDenizen +849 -0
- data/lists/huoquitlan/originalItemName +33 -0
- data/lists/huoquitlan/originalNPC +99 -0
- data/lists/huoquitlan/originalName +226 -0
- data/lists/hypotheticals/noun +373 -0
- data/lists/hypotheticals/root +15 -0
- data/lists/hypotheticals/transitiveVerb +628 -0
- data/lists/hypotheticals/verbs +653 -0
- data/lists/sophistry/root +269 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -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=
|
data/bin/dunmanifestin
ADDED
@@ -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,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
|