Class: FormatText::FTO
- Inherits:
-
String
- Object
- String
- FormatText::FTO
- Defined in:
- lib/fto.rb
Overview
Description
The FTO class is the user interface; all others are for developers modifying or extending the fto library.
FTO is a subclass of String, so all String methods work on an FTO object. FTO provides the additional format() method.
In addition to string text, the constructor (FTO.new) can take more than a single argument. Additional arguments will be stored as part of the object and will be available to the FTO#format() method at runtime.
An FTO object can be created as just a formatting string, or the constructor invocation can also include values to be applied by the FTO#format() method. At runtime the format() method can override any argument list provided at instantiation, but the latter is not lost.
Constant Summary collapse
- @@EnabledEffectors =
Hash of all currently enabled effectors, keyed by their sort key.
{}
- @@EffectorKeys =
Ordered array of effector keys (used to index @@EnabledEffectors)
[]
Instance Attribute Summary collapse
-
#safe ⇒ Object
Not yet implemented Controls whether the final string is built safely and conservatively, or if the output of each effector can alter the input to subsequent ones.
Class Method Summary collapse
-
.clearEffectorList ⇒ Object
Clear all effectors from the list (as a prelude to using a different syntax, for instance).
-
.destroyEffector(id) ⇒ Object
Completely removes the effector with the specified ID from the FTO system.
-
.disableEffector(id) ⇒ Object
Disables the effector with the specified ID (such as from FTO.findEffectors()).
-
.effectors ⇒ Object
Debugging class method to access list of registered effectors.
-
.eKeys ⇒ Object
Debugging class method to access list of effector keys.
-
.enableEffector(id) ⇒ Object
Enables the effector with the specified ID (found in the effector’s id attribute).
-
.findEffectors(pattern) ⇒ Object
Returns an array of registered effectors whose names (name attribute) match the specified pattern.
-
.rebuildEffectorList ⇒ Object
:stopdoc:.
-
.regex ⇒ Object
Debugging class method to access regular expression used to find effectors.
-
.registerEffector(*args) ⇒ Object
Add an effector description to the list of those which will be processed by the FTO#format() method.
Instance Method Summary collapse
-
#format(*argListp) ⇒ Object
Process the formatting string, optionally with a runtime argument list.
-
#initialize(text = nil, *args) ⇒ FTO
constructor
Any argument list is supplied at object instantiation can be temporarily overridden when the FTO#format() method is invoked.
-
#String_initialize ⇒ Object
:stopdoc:.
Constructor Details
#initialize(text = nil, *args) ⇒ FTO
Any argument list is supplied at object instantiation can be temporarily overridden when the FTO#format() method is invoked.
:call-seq:
new<i>()</i> => <i>FTO object</i>
new<i>(String)</i> => <i>FTO object</i>
new<i>(String, arg [, ...])</i> => <i>FTO object</i>
293 294 295 296 297 |
# File 'lib/fto.rb', line 293 def initialize(text=nil, *args) String_initialize(text) @safe = true @args = args end |
Instance Attribute Details
#safe ⇒ Object
Not yet implemented Controls whether the final string is built safely and conservatively, or if the output of each effector can alter the input to subsequent ones.
250 251 252 |
# File 'lib/fto.rb', line 250 def safe @safe end |
Class Method Details
.clearEffectorList ⇒ Object
Clear all effectors from the list (as a prelude to using a different syntax, for instance).
:call-seq:
FTO.clearEffectorList<i>()</i> => <i>nil</i>
306 307 308 309 310 |
# File 'lib/fto.rb', line 306 def self.clearEffectorList() @@RegisteredEffectors.delete_if { |id,e| true } self.rebuildEffectorList() nil end |
.destroyEffector(id) ⇒ Object
Completely removes the effector with the specified ID from the FTO system. THIS IS NOT REVERSIBLE!
:call-seq:
FTO.destroyEffector<i>(Fixnum)</i> => <i>nil</i>
384 385 386 387 |
# File 'lib/fto.rb', line 384 def self.destroyEffector(id) @@RegisteredEffectors.delete(id) self.rebuildEffectorList() end |
.disableEffector(id) ⇒ Object
Disables the effector with the specified ID (such as from FTO.findEffectors()). This is a no-op if the effector is already disabled.
:call-seq:
FTO.disableEffector<i>(Fixnum)</i> => <i>nil</i>
397 398 399 400 401 402 403 |
# File 'lib/fto.rb', line 397 def self.disableEffector(id) if ((e = @@RegisteredEffectors[id]).nil?) raise RuntimeError, _('No such effector ') + "ID\##{id}" end e.disable nil end |
.effectors ⇒ Object
Debugging class method to access list of registered effectors
264 265 266 |
# File 'lib/fto.rb', line 264 def self.effectors() # :nodoc: @@RegisteredEffectors end |
.eKeys ⇒ Object
Debugging class method to access list of effector keys.
271 272 273 |
# File 'lib/fto.rb', line 271 def self.eKeys() # :nodoc: @@EffectorKeys end |
.enableEffector(id) ⇒ Object
Enables the effector with the specified ID (found in the effector’s id attribute). This is a no-op if the effector is already enabled.
:call-seq:
FTO.enableEffector<i>(Fixnum)</i> => <i>nil</i>
369 370 371 372 373 374 375 |
# File 'lib/fto.rb', line 369 def self.enableEffector(id) if ((e = @@RegisteredEffectors[id]).nil?) raise RuntimeError, _('No such effector ') + "ID\##{id}" end e.enabled = true self.rebuildEffectorList() end |
.findEffectors(pattern) ⇒ Object
Returns an array of registered effectors whose names (name attribute) match the specified pattern.
:call-seq:
FTO.findEffectors<i>(String)</i> => <i>Array</i>
FTO.findEffectors<i>(Regexp)</i> => <i>Array</i>
413 414 415 416 417 |
# File 'lib/fto.rb', line 413 def self.findEffectors(pattern) pattern = Regexp.new(pattern) unless (pattern.class == Regexp) matches = @@RegisteredEffectors.select { |id,e| e.name.match(pattern) } matches.collect { |id,e| e } end |
.rebuildEffectorList ⇒ Object
:stopdoc:
This class method rebuilds the regular expression and the hash of enabled effectors. It needs to be invoked any time an effector is added, destroyed, enabled, or disabled. It’s for internal use only.
347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/fto.rb', line 347 def self.rebuildEffectorList() enabled = @@RegisteredEffectors.select { |id,e| e.enabled? } @@EffectorKeys = [] @@EffectorKeys = enabled.collect { |k,e| e.sortKey }.sort @@EffectorKeys.freeze @@EnabledEffectors = {} enabled.each { |k,e| @@EnabledEffectors[e.sortKey] = e } @@EnabledEffectors.freeze @@regex = Regexp.new("(#{@@EffectorKeys.collect {|k| @@EnabledEffectors[k].reMatch}.join(')|(')})") @@regex.freeze nil end |
.regex ⇒ Object
Debugging class method to access regular expression used to find effectors.
279 280 281 |
# File 'lib/fto.rb', line 279 def self.regex() # :nodoc: @@regex end |
.registerEffector(*args) ⇒ Object
Add an effector description to the list of those which will be processed by the FTO#format() method.
:call-seq:
FTO.registerEffector<i>(FormatText::Effector)</i> => <i>nil</i>
FTO.registerEffector<i>({ :symattr => value [, ...] })</i> => <i>nil</i>
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/fto.rb', line 320 def self.registerEffector(*args) if ((args.length == 1) && (args[0].class.name.match(/Effector$/))) newE = args[0] else newE = Effector.new('placeholder') if ((args.length == 1) && (args[0].class == Hash)) args[0].each do |key,val| eval("newE.#{key.to_s} = val") end else newE = Effector.new(args) end end key = sprintf('%06d-%s', newE.priority, newE.name) newE.sortKey = key @@RegisteredEffectors[newE.id] = newE self.rebuildEffectorList() nil end |
Instance Method Details
#format(*argListp) ⇒ Object
Process the formatting string, optionally with a runtime argument list. The argument list can either be a list of values, an array of values, or a FormatText::Context object. (The latter is intended only for internal use with recursion.)
:call-seq:
format<i>()</i> => <i>String</i>
format<i>(arg [, ...])</i> => <i>String</i>
format<i>(Array)</i> => <i>String</i>
format<i>(FormatText::Context)</i> => <i>String</i> (<u>internal use only</u>)
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 |
# File 'lib/fto.rb', line 432 def format(*argListp) argList = argListp.empty? ? @args.clone : argListp if ((argList.length == 1) && (argList[0].class == Array)) && argList = argList[0] end # # It's possible we were passed a Context object so we can # recurse. If so, use its values for some of these. # if ((argList.length == 1) && (argList[0].class == FormatText::Context)) eContext = argList[0] usedArgs = eContext.usedArgs argList = eContext.argList else usedArgs = [] eContext = Context.new({ :ftoObj => self, :usedArgs => usedArgs, :argList => argList }) end input = self.to_s output = input.clone effector = sMatched = nil while (m = input.match(@@regex)) # # Find out which effector was matched. The index in .captures # will be the same as the index in @effectors. # m.captures.length.times do |i| next if (m.captures[i].nil?) eContext.effectorObj = effector = @@EnabledEffectors[@@EffectorKeys[i]] eContext.sMatched = sMatched = m.captures[i] eContext.reuseArg = false break end # # Call the workhorse for this descriptor # replacement = effector.code.call(eContext) output.sub!(sMatched, replacement) input.sub!(sMatched, '') # # Mark the item at the front of the argument list as having # been used, if the effector agrees. Assume that an argument # was actually used if we're moving it, and that the 'last # argument used' hasn't changed if the effector has set # _reuseArg_. # unless (eContext.reuseArg) usedArgs.push(argList.shift) eContext.lastArgUsed = usedArgs.last end end output end |
#String_initialize ⇒ Object
:stopdoc:
We do this in order to call super on String, but since our argument list is different, we need to finesse it a little. Nobody’s business but ours.
258 |
# File 'lib/fto.rb', line 258 alias_method(:String_initialize, :initialize) |