Class: Lcsort
- Inherits:
-
Object
- Object
- Lcsort
- Defined in:
- lib/lcsort.rb,
lib/lcsort/version.rb,
lib/lcsort/volume_abbreviations.rb
Overview
Constant Summary collapse
- HIGH_CHAR =
'~'
- LC =
/^ \s* ([A-Z]{1,3}) # alpha \s* (?: # optional numbers with optional decimal point (\d+) # num (?:\s*?\.\s*?(\d+))? # dec )? \s* (?: # optional doon1 -- date or other number eg 1991 , 103rd, 103d \.? (\d{1,4}) (?:ST|ND|RD|TH|D)? )? \s* (?: # optional cutter \.? \s* ([A-Z]) # cutter letter c1alpha # cutter numeric portion is optional entirely IF at end of string, to # support bottomout on partial cutters # optional cutter letter suffixes are also supported # ie .A12ab -- which requires lookahead to make sure not absorbing subsequent # cutter, doh. \s* (\d+ # cutter numbers c1num (?: [a-zA-Z]{0,2}(?=[ \.]|\Z))? # ...with optional 1-2 letter suffix | \Z) )? \s* (?: # optional doon2 -- date or other number eg 1991 , 103rd, 103d \.? (\d{1,4}) (?:ST|ND|RD|TH|D|Q)? )? \s* (?: # optional cutter \.? \s* ([A-Z]) # cutter letter c2alpha \s* (\d+ # cutter numbers c2num (?: [a-zA-Z]{0,2}(?=[ \.]|\Z))? # ...with optional 1-2 letter suffix | \Z) )? \s* (?: # optional cutter \.? \s* ([A-Z]) # cutter letter c3alpha \s* (\d+ # cutter numbers c3num (?: [a-zA-Z]{0,2}(?=[ \.]|\Z))? # ...with optional 1-2 letter suffix | \Z) )? (\s+.+?)? # everthing else extra \s*$/x
- VERSION =
"0.9.1"
- VolumeAbbreviations =
abbrevs
Instance Attribute Summary collapse
-
#alpha_width ⇒ Object
Returns the value of attribute alpha_width.
-
#append_suffix_separator ⇒ Object
Returns the value of attribute append_suffix_separator.
-
#class_letter_padding ⇒ Object
Returns the value of attribute class_letter_padding.
-
#class_whole_width ⇒ Object
Returns the value of attribute class_whole_width.
-
#cutter_extralow_separator ⇒ Object
Returns the value of attribute cutter_extralow_separator.
-
#doon_width ⇒ Object
Returns the value of attribute doon_width.
-
#extra_num_regexp ⇒ Object
Returns the value of attribute extra_num_regexp.
-
#extra_separator ⇒ Object
Returns the value of attribute extra_separator.
-
#extra_vol_num_width ⇒ Object
Returns the value of attribute extra_vol_num_width.
-
#low_prefix_separator ⇒ Object
Returns the value of attribute low_prefix_separator.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize ⇒ Lcsort
constructor
A new instance of Lcsort.
-
#left_fill_number(content, width) ⇒ Object
Left-pad a whole number with zeroes to specified width.
- #normalize(cn, options = {}) ⇒ Object
- #normalize_append_suffix(suffix) ⇒ Object
- #normalize_cutter(c_alpha_prefix, c_rest) ⇒ Object
- #normalize_doon(doon) ⇒ Object
-
#normalize_extra(extra) ⇒ Object
The ‘extra’ component is normalized by making it all alphanumeric, and adding an ultra low prefix separator.
- #right_fill(content, width, padding) ⇒ Object
- #truncated_range_end(callnum) ⇒ Object
Constructor Details
#initialize ⇒ Lcsort
Returns a new instance of Lcsort.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/lcsort.rb', line 74 def initialize() self.alpha_width = 3 self.class_whole_width = 4 self.doon_width = 4 self.extra_vol_num_width = 4 # cutter prefix separator must be lower ascii value than digit 0, # but higher than cutter_extralow_separator. `.` gives us # something that makes debugging easy and doesn't need to be # URI-escaped, which is nice. self.low_prefix_separator = '.' # cutter extralow separator separates cutter letter suffixes # ei as in the 'ab' A234ab. It must be LOWER ascii value than # low_prefix_separator to make sort work. # Could use space ` `, but `-` is # less confusing debugging and nice that it doesn't need to be URI-escaped. self.cutter_extralow_separator = '-' # Using anything less than ascii 0 should work, but `.` is nice for # debugging. self.class_letter_padding = '.' # Extra separator needs to be lower than our other separators, # especially cutter_extralow_separator. # Doubling the cutter_extralow_separator works. self.extra_separator = (self.cutter_extralow_separator * 2) # Needs to sort LOWER than extra separator, at least in cases # where there's no extra. We tried comma, but MySQL did weird # things under utf8 collation. Let's see if it works better with # three dashes. self.append_suffix_separator = (self.cutter_extralow_separator * 3) # Only state should be configuration, not about individual call numbers. # We re-use this for multiple call numbers, and don't want callnum-specific # state; we also want to ensure it's thread-safe for using between multiple # threads. So freeze it! Doesn't absolutely prevent state changes, but # helps and sends the message. self.freeze end |
Instance Attribute Details
#alpha_width ⇒ Object
Returns the value of attribute alpha_width.
70 71 72 |
# File 'lib/lcsort.rb', line 70 def alpha_width @alpha_width end |
#append_suffix_separator ⇒ Object
Returns the value of attribute append_suffix_separator.
71 72 73 |
# File 'lib/lcsort.rb', line 71 def append_suffix_separator @append_suffix_separator end |
#class_letter_padding ⇒ Object
Returns the value of attribute class_letter_padding.
71 72 73 |
# File 'lib/lcsort.rb', line 71 def class_letter_padding @class_letter_padding end |
#class_whole_width ⇒ Object
Returns the value of attribute class_whole_width.
70 71 72 |
# File 'lib/lcsort.rb', line 70 def class_whole_width @class_whole_width end |
#cutter_extralow_separator ⇒ Object
Returns the value of attribute cutter_extralow_separator.
71 72 73 |
# File 'lib/lcsort.rb', line 71 def cutter_extralow_separator @cutter_extralow_separator end |
#doon_width ⇒ Object
Returns the value of attribute doon_width.
70 71 72 |
# File 'lib/lcsort.rb', line 70 def doon_width @doon_width end |
#extra_num_regexp ⇒ Object
Returns the value of attribute extra_num_regexp.
72 73 74 |
# File 'lib/lcsort.rb', line 72 def extra_num_regexp @extra_num_regexp end |
#extra_separator ⇒ Object
Returns the value of attribute extra_separator.
71 72 73 |
# File 'lib/lcsort.rb', line 71 def extra_separator @extra_separator end |
#extra_vol_num_width ⇒ Object
Returns the value of attribute extra_vol_num_width.
70 71 72 |
# File 'lib/lcsort.rb', line 70 def extra_vol_num_width @extra_vol_num_width end |
#low_prefix_separator ⇒ Object
Returns the value of attribute low_prefix_separator.
71 72 73 |
# File 'lib/lcsort.rb', line 71 def low_prefix_separator @low_prefix_separator end |
Class Method Details
.normalize(*args) ⇒ Object
126 127 128 |
# File 'lib/lcsort.rb', line 126 def self.normalize(*args) @global.normalize(*args) end |
.truncated_range_end(*args) ⇒ Object
130 131 132 |
# File 'lib/lcsort.rb', line 130 def self.truncated_range_end(*args) @global.truncated_range_end(*args) end |
Instance Method Details
#left_fill_number(content, width) ⇒ Object
Left-pad a whole number with zeroes to specified width
212 213 214 215 216 217 218 |
# File 'lib/lcsort.rb', line 212 def left_fill_number(content, width) content = content.to_s fill_spots = width - content.length fill_spots = 0 if fill_spots < 0 return ('0' * fill_spots) + content end |
#normalize(cn, options = {}) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/lcsort.rb', line 134 def normalize(cn, = {}) callnum = cn.upcase match = LC.match(callnum) unless match return nil end alpha, num, dec, doon1, c1alpha, c1num, doon2, c2alpha, c2num, c3alpha, c3num, extra = match.captures # We can't handle a class number wider than the space we have if num && num.length > self.class_whole_width return nil end normal_str = "" # Right fill alpha class with separators, to ensure sort, we # always have alpha. normal_str << right_fill( alpha, alpha_width, self.class_letter_padding) # Left-fill whole number with preceding 0's to ensure sort, # Only needed if present, sort will work right regardless. if num normal_str << left_fill_number(num, class_whole_width) end # decimal class number needs no fill, add it if we have it. # relies on fixed width whole number to sort properly. normal_str << dec if dec # Add cutters and doons in order, if present normal_str << normalize_doon(doon1) if doon1 normal_str << normalize_cutter(c1alpha, c1num) if c1alpha normal_str << normalize_doon(doon2) if doon2 normal_str << normalize_cutter(c2alpha, c2num) if c2alpha normal_str << normalize_cutter(c3alpha, c3num) if c3alpha normal_str << normalize_extra(extra) if extra normal_str << normalize_append_suffix([:append_suffix]) if [:append_suffix] # normally we REQUIRE an alpha and number for a good call number, # but for creating truncated_end_ranges, we relax that. unless [:range_end_construction] unless alpha && num return nil end end return normal_str end |
#normalize_append_suffix(suffix) ⇒ Object
253 254 255 |
# File 'lib/lcsort.rb', line 253 def normalize_append_suffix(suffix) self.append_suffix_separator + suffix end |
#normalize_cutter(c_alpha_prefix, c_rest) ⇒ Object
220 221 222 223 224 225 226 227 228 |
# File 'lib/lcsort.rb', line 220 def normalize_cutter(c_alpha_prefix, c_rest) return nil if c_alpha_prefix.nil? || c_rest.nil? # Put a low separator before alpha suffix if present, to # ensure sort. c_rest = c_rest.sub(/(.*\d)([a-zA-Z]{1,2})\Z/, "\\1#{self.cutter_extralow_separator}\\2") self.low_prefix_separator + c_alpha_prefix + c_rest end |
#normalize_doon(doon) ⇒ Object
230 231 232 233 234 |
# File 'lib/lcsort.rb', line 230 def normalize_doon(doon) return nil if doon.nil? self.low_prefix_separator + left_fill_number(doon, self.doon_width) end |
#normalize_extra(extra) ⇒ Object
The ‘extra’ component is normalized by making it all alphanumeric, and adding an ultra low prefix separator.
238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
# File 'lib/lcsort.rb', line 238 def normalize_extra(extra) # Left-pad any volume/number type designations with zeros, so # they sort appropriately. We just find ALL numbers and # normalize them accordingly, it's good enough! extra_normalized = extra.gsub(/(\d+)/) do |match| left_fill_number($1, self.extra_vol_num_width) end # remove all non-alphanumeric extra_normalized = extra_normalized.gsub(/[^A-Z0-9]/, '') # Add very low prefix separator return (self.extra_separator + extra_normalized) end |
#right_fill(content, width, padding) ⇒ Object
203 204 205 206 207 208 209 |
# File 'lib/lcsort.rb', line 203 def right_fill(content, width, padding) content = content.to_s fill_spots = width - content.length fill_spots = 0 if fill_spots < 0 content.to_s + (padding * fill_spots) end |
#truncated_range_end(callnum) ⇒ Object
191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/lcsort.rb', line 191 def truncated_range_end(callnum) # Tell normalize to relax it's restrictions for range_end # construction. normalized = normalize(callnum, :range_end_construction => true) return nil unless normalized # We just add a HIGH_CHAR on the end to make sure this sorts # after the original normalized with ANYTHING else on the end. return normalized + HIGH_CHAR end |