Class: IsoDoc::XrefGen::Counter
- Includes:
- OlTypeProvider
- Defined in:
- lib/isodoc/xref/xref_counter.rb
Instance Attribute Summary collapse
-
#prefix_override ⇒ Object
Returns the value of attribute prefix_override.
Instance Method Summary collapse
- #blank?(str) ⇒ Boolean
- #clock_letter ⇒ Object
- #increment(node) ⇒ Object
- #increment_letter ⇒ Object
-
#initialize(num = 0, opts = { numerals: :arabic }) ⇒ Counter
constructor
A new instance of Counter.
- #listlabel(list, depth) ⇒ Object
- #new_subseq_increment(node) ⇒ Object
- #new_subseq_increment1(node) ⇒ Object
-
#parse_number_suffix(str) ⇒ Object
Decompose a counter number string into [prefix, digits, letters] by scanning from the right.
- #print ⇒ Object
- #reset_overrides ⇒ Object
- #sequence_increment(node) ⇒ Object
- #string_inc(str, start) ⇒ Object
- #style_number(num) ⇒ Object
- #subsequence_increment(node) ⇒ Object
- #subsequence_increment_no_letter(node) ⇒ Object
Methods included from OlTypeProvider
Constructor Details
#initialize(num = 0, opts = { numerals: :arabic }) ⇒ Counter
Returns a new instance of Counter.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/isodoc/xref/xref_counter.rb', line 24 def initialize(num = 0, opts = { numerals: :arabic }) @unnumbered = false @num = num @letter = "" @subseq = "" reset_overrides @style = opts[:numerals] @skip_i = opts[:skip_i] @prefix = opts[:prefix] @separator = opts[:separator] || "." @base = "" if num.is_a? String if /^\d+$/.match?(num) @num = num.to_i else @num = nil @base = num[0..-2] @letter = num[-1] end end end |
Instance Attribute Details
#prefix_override ⇒ Object
Returns the value of attribute prefix_override.
22 23 24 |
# File 'lib/isodoc/xref/xref_counter.rb', line 22 def prefix_override @prefix_override end |
Instance Method Details
#blank?(str) ⇒ Boolean
154 155 156 |
# File 'lib/isodoc/xref/xref_counter.rb', line 154 def blank?(str) str.nil? || str.empty? end |
#clock_letter ⇒ Object
143 144 145 146 147 148 149 150 151 152 |
# File 'lib/isodoc/xref/xref_counter.rb', line 143 def clock_letter case @letter when "Z" @letter = "@" @base = string_inc(@base, "A") when "z" @letter = "`" @base = string_inc(@base, "a") end end |
#increment(node) ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/isodoc/xref/xref_counter.rb', line 158 def increment(node) @unnumbered = node["unnumbered"] == "true" || node["hidden"] == "true" and return self reset_overrides if node["subsequence"] != @subseq && !(blank?(node["subsequence"]) && blank?(@subseq)) new_subseq_increment(node) elsif @letter.empty? then sequence_increment(node) else subsequence_increment(node) end self end |
#increment_letter ⇒ Object
136 137 138 139 140 141 |
# File 'lib/isodoc/xref/xref_counter.rb', line 136 def increment_letter clock_letter @letter = (@letter.ord + 1).chr.to_s @skip_i && %w(i I).include?(@letter) and @letter = (@letter.ord + 1).chr.to_s end |
#listlabel(list, depth) ⇒ Object
210 211 212 213 214 215 216 217 218 219 |
# File 'lib/isodoc/xref/xref_counter.rb', line 210 def listlabel(list, depth) case ol_type(list, depth) when :arabic then @num.to_s when :alphabet then (96 + @num).chr.to_s when :alphabet_upper then (64 + @num).chr.to_s when :roman then RomanNumerals.to_roman(@num).downcase when :roman_upper then RomanNumerals.to_roman(@num).upcase when :japanese then num.localize(:ja).spellout end end |
#new_subseq_increment(node) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/isodoc/xref/xref_counter.rb', line 52 def new_subseq_increment(node) @subseq = node["subsequence"] @num += 1 unless @num.nil? @letter = node["subsequence"] ? "a" : "" @base = "" new_subseq_increment1(node) if node["number"] end |
#new_subseq_increment1(node) ⇒ Object
60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/isodoc/xref/xref_counter.rb', line 60 def new_subseq_increment1(node) b, n, a = parse_number_suffix(node["number"]) if !n.empty? || !a.empty? @letter_override = @letter = a unless a.empty? @number_override = @num = n.to_i unless n.empty? @base = b else @letter_override = node["number"] @letter = @letter_override if /^[a-zA-Z]$/.match?(@letter_override) end end |
#parse_number_suffix(str) ⇒ Object
Decompose a counter number string into [prefix, digits, letters] by scanning from the right. Examples:
"A1b" => ["A", "1", "b" ]
"prefix-3" => ["prefix-", "3", "" ]
"ABC" => ["", "", "ABC" ]
"42" => ["", "42", "" ]
Replaces polynomial regexes like /^(?<b>.*?)(?<n>d*)(?<a>*)$/ with O(n) rindex operations that cannot backtrack.
198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/isodoc/xref/xref_counter.rb', line 198 def parse_number_suffix(str) # Step 1: split off all trailing letters i = str.rindex(/[^a-zA-Z]/) # index of last non-letter char a = i.nil? ? str : str[(i + 1)..] rest = i.nil? ? "" : str[..i] # Step 2: split off all trailing digits from the remaining prefix j = rest.rindex(/[^\d]/) # index of last non-digit char n = j.nil? ? rest : rest[(j + 1)..] b = j.nil? ? "" : rest[..j] [b, n, a] end |
#print ⇒ Object
180 181 182 183 184 185 186 187 188 |
# File 'lib/isodoc/xref/xref_counter.rb', line 180 def print @unnumbered and return nil @prefix_override and return @prefix_override num = @number_override || @num out = style_number(num) prefix = @prefix prefix &&= "#{prefix}#{@separator}" "#{prefix}#{@base}#{out}#{@letter_override || @letter}" end |
#reset_overrides ⇒ Object
46 47 48 49 50 |
# File 'lib/isodoc/xref/xref_counter.rb', line 46 def reset_overrides @letter_override = nil @number_override = nil @prefix_override = nil end |
#sequence_increment(node) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/isodoc/xref/xref_counter.rb', line 72 def sequence_increment(node) if node["branch-number"] @prefix_override = node["branch-number"] elsif node["number"] @base = @letter_override = @number_override = "" b, n, a = parse_number_suffix(node["number"]) # Original required digits at the absolute end (no trailing letters). # If there are trailing letters, treat as a no-digit-at-end match. n = "" unless a.empty? if blank?(n) @num = nil @base = node["number"][0..-2] @letter = @letter_override = node["number"][-1] else @number_override = @num = n.to_i @base = b @letter = "" end else @num += 1 end end |
#string_inc(str, start) ⇒ Object
130 131 132 133 134 |
# File 'lib/isodoc/xref/xref_counter.rb', line 130 def string_inc(str, start) return start if str.empty? str[0..-2] + (str[-1].ord + 1).chr.to_s end |
#style_number(num) ⇒ Object
171 172 173 174 175 176 177 178 |
# File 'lib/isodoc/xref/xref_counter.rb', line 171 def style_number(num) num.nil? and return num case @style when :roman then RomanNumerals.to_roman(num) when :japanese then num.localize(:ja).spellout else num end end |
#subsequence_increment(node) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/isodoc/xref/xref_counter.rb', line 94 def subsequence_increment(node) return increment_letter unless node["number"] @base = "" @letter_override = node["number"] # Replace polynomial /^(?<b>.*?)(?<n>\d*)(?<a>[a-zA-Z])$/ with # sequential parsing from the right: last char must be a single letter; # before it are optional digits; before that is the base prefix b. a = /[a-zA-Z]/.match?(node["number"][-1]) ? node["number"][-1] : nil if a rest = node["number"][..-2] j = rest.rindex(/[^\d]/) n = j.nil? ? rest : rest[(j + 1)..] b = j.nil? ? "" : rest[..j] end if blank?(a) then subsequence_increment_no_letter(node) else @letter_override = @letter = a @base = b @number_override = @num = n.to_i unless n.empty? end end |
#subsequence_increment_no_letter(node) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/isodoc/xref/xref_counter.rb', line 117 def subsequence_increment_no_letter(node) if /^\d+$/.match?(node["number"]) @letter_override = @letter = "" @number_override = @num = node["number"].to_i else /^(?<b>.*)(?<a>[a-zA-Z])$/ =~ node["number"] unless blank?(a) @letter = @letter_override = a @base = b end end end |