cardname 0.13.1 → 0.14.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: eccd39597d09bf9378cb085a18c37427f48c55997d4dd50c0d9d0d2bec80de11
4
- data.tar.gz: ae0ba7ff34670d3ff231c37794b83cecdc04ff75601aeaa43af1a6ba60c1b58e
3
+ metadata.gz: d42f369012c637f78375a460e4814d841ed45fee9f4f3d7eb5f9dee84f725dd0
4
+ data.tar.gz: 5bbfbdfcaaf320fa1e0853e5ec781c54b38cd9a38e41bffdb12a52820fc768ed
5
5
  SHA512:
6
- metadata.gz: ede5f7daeebd3e2ec114985adf6810a4e7778b1f61bbca4b6af397129a92fc4f1a737b9097e6da557b8297630b4a3d6eaa130d38fe5b09e63e2fec7b9e8d7191
7
- data.tar.gz: 447d668197aeb81d58c44bbe9c43779eed643fe5728430603ed0ab2333903d2087309f866b2d5c8411aade0fdf2931b653a4d1c6042dde35bc4fb08e9c02868b
6
+ metadata.gz: a3376035abe1d69ed768e6f3eb040106a87985c6a20fb9dfb939d416589f804e6c820ff325e9e819ac43d3529513cdc6fd6a03e01fd50301c7b1d958a8ad4d2d
7
+ data.tar.gz: 0ec2da901b07b528bfe7ddaaecc50a4ff8e65533d4282e51f74e9595214ebfe012cccbdff2729d4b3fd0613f7fa24eac091b25444375745a038a93d6c8583c5a
@@ -34,7 +34,8 @@ class Cardname
34
34
  name_from(*from).s
35
35
  end
36
36
 
37
- # if possible, relativize name into one beginning with a "+". The new name must absolutize back to the correct
37
+ # if possible, relativize name into one beginning with a "+".
38
+ # The new name must absolutize back to the correct
38
39
  # original name in the context of "from"
39
40
  def name_from *from
40
41
  return self unless (remaining = remove_context(*from))
@@ -38,6 +38,10 @@ class Cardname
38
38
  parts.length
39
39
  end
40
40
 
41
+ def [] *args
42
+ self.class.new part_names[*args]
43
+ end
44
+
41
45
  def prepend_joint
42
46
  joint = self.class.joint
43
47
  self =~ /^#{Regexp.escape joint}/ ? self : (joint + self)
@@ -3,106 +3,92 @@ class Cardname
3
3
  # methods that end with _name return name objects
4
4
  # the same methods without _name return strings
5
5
  module Parts
6
- attr_reader :parts, :part_keys, :simple
7
- alias_method :to_a, :parts
6
+ # PARTS
7
+ def part_names
8
+ @part_names ||= generate_part_names
9
+ end
8
10
 
9
11
  def parts
10
- @parts = Cardname.split_parts s
12
+ part_names.map(&:s)
11
13
  end
14
+ alias_method :to_a, :parts
12
15
 
13
16
  def part_keys
14
- @part_keys ||= simple ? [simple_key] : parts.map { |p| p.to_name.simple_key }
17
+ part_names.map(&:key)
15
18
  end
16
19
 
17
- def left
18
- @left ||= simple? ? nil : parts[0..-2] * self.class.joint
19
- end
20
-
21
- def right
22
- @right ||= simple? ? nil : parts[-1]
20
+ def trunk_name
21
+ simple? ? self : left_name
23
22
  end
24
23
 
25
- def left_name
26
- @left_name ||= left && self.class.new(left)
24
+ def trunk
25
+ trunk_name.s
27
26
  end
28
27
 
29
- def right_name
30
- @right_name ||= right && self.class.new(right)
28
+ def trunk_key
29
+ trunk_name.key
31
30
  end
32
31
 
33
- def left_key
34
- @left_key ||= simple? ? nil : part_keys[0..-2] * self.class.joint
32
+ def tag_name
33
+ simple? ? self : right_name
35
34
  end
36
35
 
37
- def right_key
38
- @right_key ||= simple? ? nil : part_keys.last
36
+ def tag
37
+ tag_name.s
39
38
  end
40
39
 
41
- def parents
42
- @parents ||= compound? ? [left, right] : []
40
+ def tag_key
41
+ tag_name.key
43
42
  end
44
43
 
45
44
  def parent_names
46
- @parent_names ||= compound? ? [left_name, right_name] : []
45
+ simple? ? [] : [left_name, right_name]
47
46
  end
48
47
 
49
- def parent_keys
50
- @parent_keys ||= compound? ? [left_key, right_key] : []
48
+ def parents
49
+ parent_names.map(&:s)
51
50
  end
52
51
 
53
- # Note that all names have a trunk and tag,
54
- # but only junctions have left and right
55
-
56
- def trunk
57
- @trunk ||= simple? ? s : left
52
+ def parent_keys
53
+ parent_names.map(&:key)
58
54
  end
59
55
 
60
- def tag
61
- @tag ||= simple? ? s : right
56
+ def left_name
57
+ simple? ? nil : self.class.new(part_names[0..-2])
62
58
  end
63
59
 
64
- def trunk_name
65
- @trunk_name ||= simple? ? self : left_name
60
+ def left
61
+ left_name&.s
66
62
  end
67
63
 
68
- def tag_name
69
- @tag_name ||= simple? ? self : right_name
64
+ def left_key
65
+ left_name&.key
70
66
  end
71
67
 
72
- def part_names
73
- @part_names ||= parts.map(&:to_name)
68
+ def right_name
69
+ simple? ? nil : part_names[-1]
74
70
  end
75
71
 
76
- def piece_names
77
- @piece_names ||= pieces.map(&:to_name)
72
+ def right
73
+ right_name&.s
78
74
  end
79
75
 
80
- def ancestors
81
- @ancestors ||= pieces.reject { |p| p == self }
76
+ def right_key
77
+ right_name&.key
82
78
  end
83
79
 
84
- # def + other
85
- # self.class.new(parts + other.to_name.parts)
86
- # end
80
+ private
87
81
 
88
- def [] *args
89
- self.class.new parts[*args]
82
+ def generate_part_names
83
+ return blank_part_names if blank?
84
+ parts = Cardname.split_parts s
85
+ @simple = parts.size <= 1
86
+ @simple ? [self] : parts.map(&:to_name)
90
87
  end
91
88
 
92
- # full support of array methods caused trouble with `flatten` calls
93
- # It splits the parts of names in arrays
94
- # # name parts can be accessed and manipulated like an array
95
- # def method_missing method, *args, &block
96
- # if ARRAY_METHODS.include? method # parts.respond_to?(method)
97
- # self.class.new parts.send(method, *args, &block)
98
- # else
99
- # super
100
- # end
101
- # end
102
- #
103
- # def respond_to? method, include_private=false
104
- # return true if ARRAY_METHODS.include? method
105
- # super || parts.respond_to?(method, include_private)
106
- # end
89
+ def blank_part_names
90
+ @simple = true
91
+ []
92
+ end
107
93
  end
108
94
  end
@@ -8,7 +8,15 @@ class Cardname
8
8
  # "A+B+C+D".to_name.pieces
9
9
  # # => ["A", "B", "C", "D", "A+B", "A+B+C", "A+B+C+D"]
10
10
  def pieces
11
- @pieces ||= simple? ? [self] : (parts + junction_pieces)
11
+ simple? ? [self] : (parts + junction_pieces)
12
+ end
13
+
14
+ def piece_names
15
+ pieces.map(&:to_name)
16
+ end
17
+
18
+ def ancestors
19
+ pieces.reject { |p| p == self }
12
20
  end
13
21
 
14
22
  private
@@ -1,15 +1,15 @@
1
1
  class Cardname
2
2
  module Predicates
3
+ # @return true if name has only one part
3
4
  def simple?
4
- @simple.nil? ? (@simple = parts.size <= 1) : @simple
5
+ part_names if @simple.nil?
6
+ @simple
5
7
  end
6
- alias_method :simple, :simple? # @deprecated
7
8
 
8
9
  # @return true if name has more than one part
9
10
  def compound?
10
11
  !simple?
11
12
  end
12
- alias_method :junction?, :compound? # @deprecated
13
13
 
14
14
  def valid?
15
15
  return true if self.class.nothing_banned?
@@ -10,12 +10,12 @@ class Cardname
10
10
  .gsub(/[^#{OK4KEY_RE}]+/, "_")
11
11
  .split(/_+/)
12
12
  .reject(&:empty?)
13
- .map { |key| self.class.stable_key(key) }
13
+ .map { |key| stable_key(key) }
14
14
  .join("_")
15
15
  end
16
16
 
17
17
  def url_key
18
- @url_key ||= part_names.map do |part_name|
18
+ part_names.map do |part_name|
19
19
  stripped = part_name.decoded.gsub(/[^#{OK4KEY_RE}]+/, " ").strip
20
20
  stripped.gsub(/[\s_]+/, "_")
21
21
  end * self.class.joint
@@ -25,7 +25,7 @@ class Cardname
25
25
  # but the key is no longer unique.
26
26
  # For example "A-XB" and "A+*B" have the same safe_key
27
27
  def safe_key
28
- @safe_key ||= key.tr("*", "X").tr self.class.joint, "-"
28
+ key.tr("*", "X").tr self.class.joint, "-"
29
29
  end
30
30
 
31
31
  def decoded
@@ -35,5 +35,30 @@ class Cardname
35
35
  def to_sym
36
36
  s.to_sym
37
37
  end
38
+
39
+ private
40
+
41
+ def uninflect_method
42
+ self.class.uninflect
43
+ end
44
+
45
+ def stabilize?
46
+ self.class.stabilize
47
+ end
48
+
49
+ # Sometimes the core rule "the key's key must be itself" (called "stable" below)
50
+ # is violated. For example, it fails with singularize as uninflect method
51
+ # for Matthias -> Matthia -> Matthium
52
+ # Usually that means the name is a proper noun and not a plural.
53
+ # You can choose between two solutions:
54
+ # 1. don't uninflect if the uninflected key is not stable (stabilize = false)
55
+ # 2. uninflect until the key is stable (stabilize = true)
56
+ def stable_key name
57
+ key_one = name.send uninflect_method
58
+ key_two = key_one.send uninflect_method
59
+ return key_one unless key_one != key_two
60
+
61
+ stabilize? ? stable_key(key_two) : name
62
+ end
38
63
  end
39
64
  end
data/lib/cardname.rb CHANGED
@@ -4,12 +4,12 @@ require "active_support/inflector"
4
4
  require "htmlentities"
5
5
 
6
6
  class Cardname < String
7
- require_relative "cardname/parts"
8
- require_relative "cardname/pieces"
9
- require_relative "cardname/variants"
10
- require_relative "cardname/contextual"
11
- require_relative "cardname/predicates"
12
- require_relative "cardname/manipulate"
7
+ require "cardname/parts"
8
+ require "cardname/pieces"
9
+ require "cardname/variants"
10
+ require "cardname/contextual"
11
+ require "cardname/predicates"
12
+ require "cardname/manipulate"
13
13
 
14
14
  include Parts
15
15
  include Pieces
@@ -31,31 +31,15 @@ class Cardname < String
31
31
  JOINT_RE = Regexp.escape joint
32
32
 
33
33
  class << self
34
- def cache
35
- @cache ||= {}
36
- end
37
-
38
34
  def new obj
39
35
  return obj if obj.is_a? self.class
40
36
 
41
37
  str = stringify(obj)
42
- cached_name(str) || super(str)
43
- end
44
-
45
- def cached_name str
46
- cache[str]
47
- end
48
-
49
- def reset_cache str=nil
50
- str ? cache.delete(str) : @cache = {}
38
+ cache[str] ||= super(str)
51
39
  end
52
40
 
53
- def stringify obj
54
- if obj.is_a?(Array)
55
- obj.map(&:to_s) * joint
56
- else
57
- obj.to_s
58
- end
41
+ def reset
42
+ @cache = {}
59
43
  end
60
44
 
61
45
  def nothing_banned?
@@ -68,27 +52,22 @@ class Cardname < String
68
52
  @banned_re ||= /[#{Regexp.escape((banned_array + [joint])).join}]/
69
53
  end
70
54
 
71
- # Sometimes the core rule "the key's key must be itself" (called "stable" below) is violated
72
- # eg. it fails with singularize as uninflect method for Matthias -> Matthia -> Matthium
73
- # Usually that means the name is a proper noun and not a plural.
74
- # You can choose between two solutions:
75
- # 1. don't uninflect if the uninflected key is not stable (stabilize = false)
76
- # 2. uninflect until the key is stable (stabilize = true)
77
- def stable_key name
78
- key_one = name.send(uninflect)
79
- key_two = key_one.send(uninflect)
80
- return key_one unless key_one != key_two
81
-
82
- stabilize ? stable_key(key_two) : name
55
+ def split_parts str
56
+ str.split(/\s*#{JOINT_RE}\s*/, -1)
83
57
  end
84
58
 
85
- def dangerous_methods
86
- bang_methods = String.instance_methods.select { |m| m.to_s.end_with?("!") }
87
- %i[replace concat clear].concat bang_methods
59
+ def cache
60
+ @cache ||= {}
88
61
  end
89
62
 
90
- def split_parts str
91
- str.split(/\s*#{JOINT_RE}\s*/, -1)
63
+ private
64
+
65
+ def stringify obj
66
+ if obj.is_a?(Array)
67
+ obj.map(&:to_s) * joint
68
+ else
69
+ obj.to_s
70
+ end
92
71
  end
93
72
  end
94
73
 
@@ -97,26 +76,26 @@ class Cardname < String
97
76
  attr_reader :key
98
77
 
99
78
  def initialize str
100
- self.class.cache[str] = super str.strip.encode("UTF-8")
79
+ super str
80
+ strip!
81
+ encode! "UTF-8"
82
+ part_names # populates @part_names and @simple
83
+ decoded # populates @decoded
84
+ key # populates and freezes @key
85
+ freeze
101
86
  end
102
87
 
103
88
  def s
104
- @s ||= String.new self
89
+ String.new self
105
90
  end
106
91
  alias_method :to_s, :s
107
92
  alias_method :to_str, :s
93
+ # alias_method :dup, :clone
108
94
 
109
95
  def to_name
110
96
  self
111
97
  end
112
98
 
113
- dangerous_methods.each do |m|
114
- define_method m do |*args, &block|
115
- reset
116
- super(*args, &block)
117
- end
118
- end
119
-
120
99
  def []= index, val
121
100
  p = parts
122
101
  p[index] = val
@@ -128,25 +107,21 @@ class Cardname < String
128
107
  end
129
108
 
130
109
  def key
131
- @key ||= part_keys.join(self.class.joint)
110
+ @key ||= generate_key.freeze
132
111
  end
133
112
 
134
113
  def == other
135
- other_key =
114
+ key ==
136
115
  case
137
116
  when other.respond_to?(:key) then other.key
138
117
  when other.respond_to?(:to_name) then other.to_name.key
139
- else other.to_s
118
+ else other.to_s.to_name.key
140
119
  end
141
- other_key == key
142
120
  end
143
121
 
144
122
  private
145
123
 
146
- def reset
147
- self.class.reset_cache s
148
- instance_variables.each do |var|
149
- instance_variable_set var, nil
150
- end
124
+ def generate_key
125
+ @simple ? simple_key : part_keys.join(self.class.joint)
151
126
  end
152
127
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cardname
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.13.1
4
+ version: 0.14.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ethan McCutchen
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-08-06 00:00:00.000000000 Z
13
+ date: 2021-12-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -81,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  requirements: []
84
- rubygems_version: 3.1.6
84
+ rubygems_version: 3.2.15
85
85
  signing_key:
86
86
  specification_version: 4
87
87
  summary: Card names without all the cards