shattered_support 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/shattered_support/core_ext/class/attribute_accessors.rb +44 -0
- data/lib/shattered_support/core_ext/class/inheritable_attributes.rb +115 -0
- data/lib/shattered_support/core_ext/class/removal.rb +24 -0
- data/lib/shattered_support/core_ext/class.rb +3 -0
- data/lib/shattered_support/core_ext/dir/search.rb +25 -0
- data/lib/shattered_support/core_ext/dir.rb +5 -0
- data/lib/shattered_support/core_ext/file/search.rb +50 -0
- data/lib/shattered_support/core_ext/file.rb +5 -0
- data/lib/shattered_support/core_ext/numeric/time.rb +72 -0
- data/lib/shattered_support/core_ext/numeric.rb +5 -0
- data/lib/shattered_support/core_ext/string/access.rb +58 -0
- data/lib/shattered_support/core_ext/string/conversions.rb +19 -0
- data/lib/shattered_support/core_ext/string/inflections.rb +64 -0
- data/lib/shattered_support/core_ext/string/iterators.rb +17 -0
- data/lib/shattered_support/core_ext/string/starts_ends_with.rb +20 -0
- data/lib/shattered_support/core_ext/string.rb +13 -0
- data/lib/shattered_support/core_ext.rb +1 -0
- data/lib/shattered_support/inflections.rb +53 -0
- data/lib/shattered_support/inflector.rb +178 -0
- data/lib/shattered_support.rb +2 -64
- metadata +38 -16
- data/lib/base.rb +0 -221
- data/lib/runner.rb +0 -11
- data/lib/timer/timed_event.rb +0 -77
- data/lib/timer/timer.rb +0 -67
- data/lib/vector.rb +0 -206
@@ -0,0 +1,44 @@
|
|
1
|
+
# Extends the class object with class and instance accessors for class attributes,
|
2
|
+
# just like the native attr* accessors for instance attributes.
|
3
|
+
class Class # :nodoc:
|
4
|
+
def cattr_reader(*syms)
|
5
|
+
syms.flatten.each do |sym|
|
6
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
7
|
+
unless defined? @@#{sym}
|
8
|
+
@@#{sym} = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.#{sym}
|
12
|
+
@@#{sym}
|
13
|
+
end
|
14
|
+
|
15
|
+
def #{sym}
|
16
|
+
@@#{sym}
|
17
|
+
end
|
18
|
+
EOS
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def cattr_writer(*syms)
|
23
|
+
syms.flatten.each do |sym|
|
24
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
25
|
+
unless defined? @@#{sym}
|
26
|
+
@@#{sym} = nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.#{sym}=(obj)
|
30
|
+
@@#{sym} = obj
|
31
|
+
end
|
32
|
+
|
33
|
+
def #{sym}=(obj)
|
34
|
+
@@#{sym} = obj
|
35
|
+
end
|
36
|
+
EOS
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def cattr_accessor(*syms)
|
41
|
+
cattr_reader(*syms)
|
42
|
+
cattr_writer(*syms)
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# Retain for backward compatibility. Methods are now included in Class.
|
2
|
+
module ClassInheritableAttributes # :nodoc:
|
3
|
+
end
|
4
|
+
|
5
|
+
# Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of
|
6
|
+
# their parents' attributes, instead of just a pointer to the same. This means that the child can add elements
|
7
|
+
# to, for example, an array without those additions being shared with either their parent, siblings, or
|
8
|
+
# children, which is unlike the regular class-level attributes that are shared across the entire hierarchy.
|
9
|
+
class Class # :nodoc:
|
10
|
+
def class_inheritable_reader(*syms)
|
11
|
+
syms.each do |sym|
|
12
|
+
class_eval <<-EOS
|
13
|
+
def self.#{sym}
|
14
|
+
read_inheritable_attribute(:#{sym})
|
15
|
+
end
|
16
|
+
|
17
|
+
def #{sym}
|
18
|
+
self.class.#{sym}
|
19
|
+
end
|
20
|
+
EOS
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def class_inheritable_writer(*syms)
|
25
|
+
syms.each do |sym|
|
26
|
+
class_eval <<-EOS
|
27
|
+
def self.#{sym}=(obj)
|
28
|
+
write_inheritable_attribute(:#{sym}, obj)
|
29
|
+
end
|
30
|
+
|
31
|
+
def #{sym}=(obj)
|
32
|
+
self.class.#{sym} = obj
|
33
|
+
end
|
34
|
+
EOS
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def class_inheritable_array_writer(*syms)
|
39
|
+
syms.each do |sym|
|
40
|
+
class_eval <<-EOS
|
41
|
+
def self.#{sym}=(obj)
|
42
|
+
write_inheritable_array(:#{sym}, obj)
|
43
|
+
end
|
44
|
+
|
45
|
+
def #{sym}=(obj)
|
46
|
+
self.class.#{sym} = obj
|
47
|
+
end
|
48
|
+
EOS
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def class_inheritable_hash_writer(*syms)
|
53
|
+
syms.each do |sym|
|
54
|
+
class_eval <<-EOS
|
55
|
+
def self.#{sym}=(obj)
|
56
|
+
write_inheritable_hash(:#{sym}, obj)
|
57
|
+
end
|
58
|
+
|
59
|
+
def #{sym}=(obj)
|
60
|
+
self.class.#{sym} = obj
|
61
|
+
end
|
62
|
+
EOS
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def class_inheritable_accessor(*syms)
|
67
|
+
class_inheritable_reader(*syms)
|
68
|
+
class_inheritable_writer(*syms)
|
69
|
+
end
|
70
|
+
|
71
|
+
def class_inheritable_array(*syms)
|
72
|
+
class_inheritable_reader(*syms)
|
73
|
+
class_inheritable_array_writer(*syms)
|
74
|
+
end
|
75
|
+
|
76
|
+
def class_inheritable_hash(*syms)
|
77
|
+
class_inheritable_reader(*syms)
|
78
|
+
class_inheritable_hash_writer(*syms)
|
79
|
+
end
|
80
|
+
|
81
|
+
def inheritable_attributes
|
82
|
+
@inheritable_attributes ||= {}
|
83
|
+
end
|
84
|
+
|
85
|
+
def write_inheritable_attribute(key, value)
|
86
|
+
inheritable_attributes[key] = value
|
87
|
+
end
|
88
|
+
|
89
|
+
def write_inheritable_array(key, elements)
|
90
|
+
write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil?
|
91
|
+
write_inheritable_attribute(key, read_inheritable_attribute(key) + elements)
|
92
|
+
end
|
93
|
+
|
94
|
+
def write_inheritable_hash(key, hash)
|
95
|
+
write_inheritable_attribute(key, {}) if read_inheritable_attribute(key).nil?
|
96
|
+
write_inheritable_attribute(key, read_inheritable_attribute(key).merge(hash))
|
97
|
+
end
|
98
|
+
|
99
|
+
def read_inheritable_attribute(key)
|
100
|
+
inheritable_attributes[key]
|
101
|
+
end
|
102
|
+
|
103
|
+
def reset_inheritable_attributes
|
104
|
+
inheritable_attributes.clear
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def inherited_with_inheritable_attributes(child)
|
109
|
+
inherited_without_inheritable_attributes(child) if respond_to?(:inherited_without_inheritable_attributes)
|
110
|
+
child.instance_variable_set('@inheritable_attributes', inheritable_attributes.dup)
|
111
|
+
end
|
112
|
+
|
113
|
+
alias inherited_without_inheritable_attributes inherited
|
114
|
+
alias inherited inherited_with_inheritable_attributes
|
115
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Class #:nodoc:
|
2
|
+
def remove_subclasses
|
3
|
+
Object.remove_subclasses_of(self)
|
4
|
+
end
|
5
|
+
|
6
|
+
def subclasses
|
7
|
+
Object.subclasses_of(self).map { |o| o.to_s }
|
8
|
+
end
|
9
|
+
|
10
|
+
def remove_class(*klasses)
|
11
|
+
klasses.flatten.each do |klass|
|
12
|
+
# Skip this class if there is nothing bound to this name
|
13
|
+
next unless defined?(klass.name)
|
14
|
+
|
15
|
+
basename = klass.to_s.split("::").last
|
16
|
+
parent = klass.parent
|
17
|
+
|
18
|
+
# Skip this class if it does not match the current one bound to this name
|
19
|
+
next unless parent.const_defined?(basename) && klass = parent.const_get(basename)
|
20
|
+
|
21
|
+
parent.send :remove_const, basename unless parent == klass
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ShatteredSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module Dir #:nodoc:
|
4
|
+
module Search #:nodoc:
|
5
|
+
def self.append_features(base) #:nodoc:
|
6
|
+
super
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Dir.each_in_path will recursively yield all non-hidden
|
11
|
+
# directories from the given path.
|
12
|
+
module ClassMethods
|
13
|
+
def each_in_path(path, &block)
|
14
|
+
return unless ::File.directory? path
|
15
|
+
yield path
|
16
|
+
foreach(path) do |directory|
|
17
|
+
next if directory =~ /\..*/
|
18
|
+
each_in_path("#{path}/#{directory}", &block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module ShatteredSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module File #:nodoc:
|
4
|
+
module Search #:nodoc:
|
5
|
+
def self.append_features(base) #:nodoc:
|
6
|
+
super
|
7
|
+
base.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# File.each_in_path will recursively look for all files,
|
12
|
+
# starting at the given path.
|
13
|
+
# It will yield with each result.
|
14
|
+
def each_in_path(path)
|
15
|
+
::Dir.each_in_path(path) do |directory|
|
16
|
+
::Dir.foreach( directory ) do |filename|
|
17
|
+
resource = directory + "/#{filename}"
|
18
|
+
yield(resource) if ::File.file? resource
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# This finds all files in paths (an array or string)
|
24
|
+
# matching the given extensions:
|
25
|
+
#
|
26
|
+
# Usage:
|
27
|
+
# -File.find_by_extensions(SHATTERED_ROOT,"ogg","mp3","wav")
|
28
|
+
# -File.find_by_extension(["apps","media","plugins"], "rmaterial")
|
29
|
+
def find_by_extensions(paths, *extensions)
|
30
|
+
paths = [paths] if paths.is_a? ::String
|
31
|
+
# get rid of "." in ".ogg"
|
32
|
+
extensions.collect! { |ext| ext[0].chr == "." ? ext[1..-1] : ext }
|
33
|
+
reg_exp = /\.(#{extensions.join("|")})$/
|
34
|
+
files = []
|
35
|
+
paths.each do |path|
|
36
|
+
each_in_path(path) do |filename|
|
37
|
+
files << filename if filename =~ reg_exp
|
38
|
+
end
|
39
|
+
end
|
40
|
+
return files
|
41
|
+
end
|
42
|
+
# See File#find_by_extensions
|
43
|
+
def find_by_extension(paths, extension)
|
44
|
+
find_by_extensions(paths, extension)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ShatteredSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module Numeric #:nodoc:
|
4
|
+
# Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years.
|
5
|
+
#
|
6
|
+
# If you need precise date calculations that doesn't just treat months as 30 days, then have
|
7
|
+
# a look at Time#advance.
|
8
|
+
#
|
9
|
+
# Some of these methods are approximations, Ruby's core
|
10
|
+
# Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and
|
11
|
+
# Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision
|
12
|
+
# date and time arithmetic
|
13
|
+
module Time
|
14
|
+
def seconds
|
15
|
+
self
|
16
|
+
end
|
17
|
+
alias :second :seconds
|
18
|
+
|
19
|
+
def minutes
|
20
|
+
self * 60
|
21
|
+
end
|
22
|
+
alias :minute :minutes
|
23
|
+
|
24
|
+
def hours
|
25
|
+
self * 60.minutes
|
26
|
+
end
|
27
|
+
alias :hour :hours
|
28
|
+
|
29
|
+
def days
|
30
|
+
self * 24.hours
|
31
|
+
end
|
32
|
+
alias :day :days
|
33
|
+
|
34
|
+
def weeks
|
35
|
+
self * 7.days
|
36
|
+
end
|
37
|
+
alias :week :weeks
|
38
|
+
|
39
|
+
def fortnights
|
40
|
+
self * 2.weeks
|
41
|
+
end
|
42
|
+
alias :fortnight :fortnights
|
43
|
+
|
44
|
+
def months
|
45
|
+
self * 30.days
|
46
|
+
end
|
47
|
+
alias :month :months
|
48
|
+
|
49
|
+
def years
|
50
|
+
(self * 365.25.days).to_i
|
51
|
+
end
|
52
|
+
alias :year :years
|
53
|
+
|
54
|
+
# Reads best without arguments: 10.minutes.ago
|
55
|
+
def ago(time = ::Time.now)
|
56
|
+
time - self
|
57
|
+
end
|
58
|
+
|
59
|
+
# Reads best with argument: 10.minutes.until(time)
|
60
|
+
alias :until :ago
|
61
|
+
|
62
|
+
# Reads best with argument: 10.minutes.since(time)
|
63
|
+
def since(time = ::Time.now)
|
64
|
+
time + self
|
65
|
+
end
|
66
|
+
|
67
|
+
# Reads best without arguments: 10.minutes.from_now
|
68
|
+
alias :from_now :since
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module ShatteredSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module String #:nodoc:
|
4
|
+
# Makes it easier to access parts of a string, such as specific characters and substrings.
|
5
|
+
module Access
|
6
|
+
# Returns the character at the +position+ treating the string as an array (where 0 is the first character).
|
7
|
+
#
|
8
|
+
# Examples:
|
9
|
+
# "hello".at(0) # => "h"
|
10
|
+
# "hello".at(4) # => "o"
|
11
|
+
# "hello".at(10) # => nil
|
12
|
+
def at(position)
|
13
|
+
self[position, 1]
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the remaining of the string from the +position+ treating the string as an array (where 0 is the first character).
|
17
|
+
#
|
18
|
+
# Examples:
|
19
|
+
# "hello".from(0) # => "hello"
|
20
|
+
# "hello".from(2) # => "llo"
|
21
|
+
# "hello".from(10) # => nil
|
22
|
+
def from(position)
|
23
|
+
self[position..-1]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the beginning of the string up to the +position+ treating the string as an array (where 0 is the first character).
|
27
|
+
#
|
28
|
+
# Examples:
|
29
|
+
# "hello".to(0) # => "h"
|
30
|
+
# "hello".to(2) # => "hel"
|
31
|
+
# "hello".to(10) # => "hello"
|
32
|
+
def to(position)
|
33
|
+
self[0..position]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns the first character of the string or the first +limit+ characters.
|
37
|
+
#
|
38
|
+
# Examples:
|
39
|
+
# "hello".first # => "h"
|
40
|
+
# "hello".first(2) # => "he"
|
41
|
+
# "hello".first(10) # => "hello"
|
42
|
+
def first(limit = 1)
|
43
|
+
self[0..(limit - 1)]
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the last character of the string or the last +limit+ characters.
|
47
|
+
#
|
48
|
+
# Examples:
|
49
|
+
# "hello".last # => "o"
|
50
|
+
# "hello".last(2) # => "lo"
|
51
|
+
# "hello".last(10) # => "hello"
|
52
|
+
def last(limit = 1)
|
53
|
+
self[(-limit)..-1] || self
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'parsedate'
|
2
|
+
|
3
|
+
module ShatteredSupport #:nodoc:
|
4
|
+
module CoreExtensions #:nodoc:
|
5
|
+
module String #:nodoc:
|
6
|
+
# Converting strings to other objects
|
7
|
+
module Conversions
|
8
|
+
# Form can be either :utc (default) or :local.
|
9
|
+
def to_time(form = :utc)
|
10
|
+
::Time.send(form, *ParseDate.parsedate(self))
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_date
|
14
|
+
::Date.new(*ParseDate.parsedate(self)[0..2])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../inflector' unless defined? Inflector
|
2
|
+
module ShatteredSupport #:nodoc:
|
3
|
+
module CoreExtensions #:nodoc:
|
4
|
+
module String #:nodoc:
|
5
|
+
# Makes it possible to do "posts".singularize that returns "post" and "MegaCoolClass".underscore that returns "mega_cool_class".
|
6
|
+
module Inflections
|
7
|
+
def pluralize
|
8
|
+
Inflector.pluralize(self)
|
9
|
+
end
|
10
|
+
|
11
|
+
def singularize
|
12
|
+
Inflector.singularize(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def camelize(first_letter = :upper)
|
16
|
+
case first_letter
|
17
|
+
when :upper then Inflector.camelize(self, true)
|
18
|
+
when :lower then Inflector.camelize(self, false)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
alias_method :camelcase, :camelize
|
22
|
+
|
23
|
+
def titleize
|
24
|
+
Inflector.titleize(self)
|
25
|
+
end
|
26
|
+
alias_method :titlecase, :titleize
|
27
|
+
|
28
|
+
def underscore
|
29
|
+
Inflector.underscore(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def dasherize
|
33
|
+
Inflector.dasherize(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def demodulize
|
37
|
+
Inflector.demodulize(self)
|
38
|
+
end
|
39
|
+
|
40
|
+
def tableize
|
41
|
+
Inflector.tableize(self)
|
42
|
+
end
|
43
|
+
|
44
|
+
def classify
|
45
|
+
Inflector.classify(self)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Capitalizes the first word and turns underscores into spaces and strips _id, so "employee_salary" becomes "Employee salary"
|
49
|
+
# and "author_id" becomes "Author".
|
50
|
+
def humanize
|
51
|
+
Inflector.humanize(self)
|
52
|
+
end
|
53
|
+
|
54
|
+
def foreign_key(separate_class_name_and_id_with_underscore = true)
|
55
|
+
Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
|
56
|
+
end
|
57
|
+
|
58
|
+
def constantize
|
59
|
+
Inflector.constantize(self)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
module ShatteredSupport #:nodoc:
|
4
|
+
module CoreExtensions #:nodoc:
|
5
|
+
module String #:nodoc:
|
6
|
+
# Custom string iterators
|
7
|
+
module Iterators
|
8
|
+
# Yields a single-character string for each character in the string.
|
9
|
+
# When $KCODE = 'UTF8', multi-byte characters are yielded appropriately.
|
10
|
+
def each_char
|
11
|
+
scanner, char = StringScanner.new(self), /./mu
|
12
|
+
loop { yield(scanner.scan(char) || break) }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ShatteredSupport #:nodoc:
|
2
|
+
module CoreExtensions #:nodoc:
|
3
|
+
module String #:nodoc:
|
4
|
+
# Additional string tests.
|
5
|
+
module StartsEndsWith
|
6
|
+
# Does the string start with the specified +prefix+?
|
7
|
+
def starts_with?(prefix)
|
8
|
+
prefix = prefix.to_s
|
9
|
+
self[0, prefix.length] == prefix
|
10
|
+
end
|
11
|
+
|
12
|
+
# Does the string end with the specified +suffix+?
|
13
|
+
def ends_with?(suffix)
|
14
|
+
suffix = suffix.to_s
|
15
|
+
self[-suffix.length, suffix.length] == suffix
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/string/inflections'
|
2
|
+
require File.dirname(__FILE__) + '/string/conversions'
|
3
|
+
require File.dirname(__FILE__) + '/string/access'
|
4
|
+
require File.dirname(__FILE__) + '/string/starts_ends_with'
|
5
|
+
require File.dirname(__FILE__) + '/string/iterators'
|
6
|
+
|
7
|
+
class String #:nodoc:
|
8
|
+
include ShatteredSupport::CoreExtensions::String::Access
|
9
|
+
include ShatteredSupport::CoreExtensions::String::Conversions
|
10
|
+
include ShatteredSupport::CoreExtensions::String::Inflections
|
11
|
+
include ShatteredSupport::CoreExtensions::String::StartsEndsWith
|
12
|
+
include ShatteredSupport::CoreExtensions::String::Iterators
|
13
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.dirname(__FILE__) + "/core_ext/*.rb"].each { |file| require(file) }
|
@@ -0,0 +1,53 @@
|
|
1
|
+
Inflector.inflections do |inflect|
|
2
|
+
inflect.plural(/$/, 's')
|
3
|
+
inflect.plural(/s$/i, 's')
|
4
|
+
inflect.plural(/(ax|test)is$/i, '\1es')
|
5
|
+
inflect.plural(/(octop|vir)us$/i, '\1i')
|
6
|
+
inflect.plural(/(alias|status)$/i, '\1es')
|
7
|
+
inflect.plural(/(bu)s$/i, '\1ses')
|
8
|
+
inflect.plural(/(buffal|tomat)o$/i, '\1oes')
|
9
|
+
inflect.plural(/([ti])um$/i, '\1a')
|
10
|
+
inflect.plural(/sis$/i, 'ses')
|
11
|
+
inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
|
12
|
+
inflect.plural(/(hive)$/i, '\1s')
|
13
|
+
inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
|
14
|
+
inflect.plural(/([^aeiouy]|qu)ies$/i, '\1y')
|
15
|
+
inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
|
16
|
+
inflect.plural(/(matr|vert|ind)ix|ex$/i, '\1ices')
|
17
|
+
inflect.plural(/([m|l])ouse$/i, '\1ice')
|
18
|
+
inflect.plural(/^(ox)$/i, '\1en')
|
19
|
+
inflect.plural(/(quiz)$/i, '\1zes')
|
20
|
+
|
21
|
+
inflect.singular(/s$/i, '')
|
22
|
+
inflect.singular(/(n)ews$/i, '\1ews')
|
23
|
+
inflect.singular(/([ti])a$/i, '\1um')
|
24
|
+
inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis')
|
25
|
+
inflect.singular(/(^analy)ses$/i, '\1sis')
|
26
|
+
inflect.singular(/([^f])ves$/i, '\1fe')
|
27
|
+
inflect.singular(/(hive)s$/i, '\1')
|
28
|
+
inflect.singular(/(tive)s$/i, '\1')
|
29
|
+
inflect.singular(/([lr])ves$/i, '\1f')
|
30
|
+
inflect.singular(/([^aeiouy]|qu)ies$/i, '\1y')
|
31
|
+
inflect.singular(/(s)eries$/i, '\1eries')
|
32
|
+
inflect.singular(/(m)ovies$/i, '\1ovie')
|
33
|
+
inflect.singular(/(x|ch|ss|sh)es$/i, '\1')
|
34
|
+
inflect.singular(/([m|l])ice$/i, '\1ouse')
|
35
|
+
inflect.singular(/(bus)es$/i, '\1')
|
36
|
+
inflect.singular(/(o)es$/i, '\1')
|
37
|
+
inflect.singular(/(shoe)s$/i, '\1')
|
38
|
+
inflect.singular(/(cris|ax|test)es$/i, '\1is')
|
39
|
+
inflect.singular(/([octop|vir])i$/i, '\1us')
|
40
|
+
inflect.singular(/(alias|status)es$/i, '\1')
|
41
|
+
inflect.singular(/^(ox)en/i, '\1')
|
42
|
+
inflect.singular(/(vert|ind)ices$/i, '\1ex')
|
43
|
+
inflect.singular(/(matr)ices$/i, '\1ix')
|
44
|
+
inflect.singular(/(quiz)zes$/i, '\1')
|
45
|
+
|
46
|
+
inflect.irregular('person', 'people')
|
47
|
+
inflect.irregular('man', 'men')
|
48
|
+
inflect.irregular('child', 'children')
|
49
|
+
inflect.irregular('sex', 'sexes')
|
50
|
+
inflect.irregular('move', 'moves')
|
51
|
+
|
52
|
+
inflect.uncountable(%w(equipment information rice money species series fish sheep))
|
53
|
+
end
|