Namespace

RCodeLeveler

Main module for RCodeLeveler. requireLevel method is not part of it: it is in the global Module scope.

Constants

K_Default_Category

The default category (spaces have to be present to ensure users cannot use it)

K_Ruby_Category

The Ruby code category (spaces have to be present to ensure users cannot use it)

Public Class Methods

getLeveledFileContent(iLibraryName) click to toggle source

Get the leveled content of a specified file. This can be useful to convert files and require them then without RCodeLeveler. It can also be useful for debugging purposes.

Parameters:

  • iLibraryName (String): Name of the ruby file to require.

Return:

  • list<String>: The content of the file once levelized

  • Boolean: Is the content really different from original content ?

     # File lib/rcodeleveler.rb, line 136
136:   def RCodeLeveler.getLeveledFileContent(iLibraryName)
137:     rSourceCode = nil
138:     rDifferent = nil
139:     
140:     lExtension = File.extname(iLibraryName)
141:     if (lExtension == '')
142:       lFileNameWithExt = "#{iLibraryName}.rb"
143:     else
144:       lFileNameWithExt = iLibraryName
145:     end
146:     lRealFileName = RCodeLeveler::getRealLibraryPath(iLibraryName)
147:     if (lRealFileName != nil)
148:       rSourceCode, rDifferent = RCodeLeveler::getSourceFileContentLevelized(lRealFileName)
149:     else
150:       # Dump error
151:       lDirList = $:.join(', ')
152:       raise LoadError, "Unable to find file #{iLibraryName}. List of directories searched: #{lDirList}. Please use getLeveledFileContent with Ruby source files only."
153:     end
154:     
155:     return rSourceCode, rDifferent
156:   end
resetLevels() click to toggle source

Reset all levels.

     # File lib/rcodeleveler.rb, line 104
104:   def RCodeLeveler.resetLevels
105:     $RCLLevels = {K_Default_Category => 0}
106:   end
setLevel(iLevel, iCategory = K_Default_Category) click to toggle source

Set a level for a category.

Parameters:

  • iLevel (Integer): The level

  • iCategory (String): The category name [optional = K_Default_Category]

     # File lib/rcodeleveler.rb, line 113
113:   def RCodeLeveler.setLevel(iLevel, iCategory = K_Default_Category)
114:     $RCLLevels[iCategory] = iLevel
115:   end
setOutputDirectory(iDirectory = nil) click to toggle source

Set an optional output directory where all leveled files required using requireLevel will be written. Reset it by setting it to nil.

Parameters:

  • iDirectory (String): The directory to write files into [optional = nil]

     # File lib/rcodeleveler.rb, line 123
123:   def RCodeLeveler.setOutputDirectory(iDirectory = nil)
124:     $RCLOutputDirectory = iDirectory
125:   end
setWarningSeverity(iWarningSeverity) click to toggle source

Set warning severity. 0: No warning. 1: Display them on stderr. 2: Throw an exception (default)

Parameters:

  • iWarningSeverity (Integer): Severity of warnings

     # File lib/rcodeleveler.rb, line 99
 99:   def RCodeLeveler.setWarningSeverity(iWarningSeverity)
100:     $RCLWarningSeverity = iWarningSeverity
101:   end

Private Class Methods

getRealLibraryPath(iLibraryName) click to toggle source

Get the library file location. This method should search for the file EXACTLY the same way Ruby does. It has been coded bearing in mind the specifications of require and load methods of Kernel module as explained in “Programming Ruby - The Pragmatic Programmers’ Guide” Second Edition - by Dave Thomas (thanks Dave by the way for your excellent book !) It appears Ruby’s behaviour comes from the method “file.c:rb_find_file(path)” (Ruby 1.8.5).

Parameters:

  • iLibraryName (String): Name of the library to load, as given to require and load methods

Return:

  • String: The name of the real source file (or nil if none found)

     # File lib/rcodeleveler.rb, line 203
203:   def RCodeLeveler.getRealLibraryPath(iLibraryName)
204:     lRealFileName = nil
205:     
206:     lExtension = File.extname(iLibraryName)
207:     if (lExtension == '')
208:       lFileNameWithExt = "#{iLibraryName}.rb"
209:     else
210:       lFileNameWithExt = iLibraryName
211:     end
212:     # Find the real file
213:     if ((lExtension == '') or
214:         (lExtension == '.rb'))
215:       if (File.expand_path(iLibraryName) == iLibraryName)
216:         # Absolute form
217:         if (File.exist?(lFileNameWithExt))
218:           lRealFileName = lFileNameWithExt
219:         end
220:       else
221:         # Relative form
222:         # Find in each directory of $:
223:         $:.each do |iDir|
224:           lFilePathAttempt = "#{iDir}/#{lFileNameWithExt}"
225:           if (File.exist?(lFilePathAttempt))
226:             # We found it
227:             lRealFileName = lFilePathAttempt
228:             break
229:           end
230:         end
231:       end
232:       # lRealFileName contains the real file name, or nil if none found
233:     end
234:     
235:     return lRealFileName
236:   end
getSourceFileContentLevelized(iFileName, iOutputFileName = nil) click to toggle source

Get the content of a file once levelized.

Parameters:

  • iFileName (String): Path to the source file to level

  • iOutputFileName (String): If set, specifies a file name to write the leveled file [optional = nil]

Return:

  • list<String>: The content of the file once levelized

  • Boolean: Is the content really different from original content ?

     # File lib/rcodeleveler.rb, line 246
246:   def RCodeLeveler.getSourceFileContentLevelized(iFileName, iOutputFileName = nil)
247:     lNewFileContents = []
248:     lFoundUsefulLVLMacro = false
249:     
250:     # The stack of level sections
251:     # list< [ String,  Integer ] >
252:     #         Category Level
253:     lLevelSections = []
254:     # The map of highest level sections
255:     # map< String,  Integer ] >
256:     #      Category HighestLevel
257:     lHighestLevelSections = {}
258:     #puts "----- $RCLLevels=#{$RCLLevels}"
259:     # First read the source file
260:     File.open(iFileName, 'r') do |iOrgFile|
261:       lLineNumber = 1
262:       # The section that currently disables our lines of code
263:       # [ String,  Integer ]
264:       #   Category Level
265:       lLevelingSection = nil
266:       iOrgFile.readlines.each do |iCodeLine|
267:         # Here is the main algorithm of the leveler.
268:         # It recognizes the following special comment lines:
269:         #   #__LVL__ <Number> <Code>: Activate the code <Code> for a default level >= <Number>.
270:         #   #__LVLCAT__ <Category> <Number> <Code>: Activate the code <Code> for a category level >= <Number>.
271:         #   #__LVLBEGIN__ <Number>: The following lines of the file are activated for a default level >= <Number>. It is a level section.
272:         #   #__LVLCATBEGIN__ <Category> <Number>: The following lines of the file are activated for a category level >= <Number>. It is a level section.
273:         #   #__LVLEND__: Terminate a level section of code that began with __LVLBEGIN__ or __LVLBEGINCAT__ comment (terminate the last opened one).
274:         lLineStripped = iCodeLine.strip
275:         # The line storing the output (by default it is the input if the last level section authorizes it)
276:         # Check if we are in a context (from $RCLLevels) that filters our current level sections' stack
277:         if (lLevelingSection == nil)
278:           lOutputLine = iCodeLine
279:         else
280:           lFoundUsefulLVLMacro = true
281:           lOutputLine = "# ! Level #{lLevelingSection[0]}.#{lLevelingSection[1]} ! #{iCodeLine}"
282:         end
283:         # Do we have to evaluate whether we have to evaluate the section or not after processing this line ?
284:         lReevaluateLevelingSection = false
285:         #puts "----- Line = #{iCodeLine}"
286:         # Interpret it
287:         if (lLineStripped[0..7] == '#__LVL__')
288:           lLineArguments = lLineStripped.scan(/^#__LVL__ ([0-9]*) (.*)$/)
289:           if (lLineArguments.size != 1)
290:             warning("#{iFileName}:#{lLineNumber}: Malformed line: #{lLineStripped}")
291:             lOutputLine = "# !!! Malformed line: #{lLineStripped}\n"
292:           else
293:             # Check that the level of this line is greater or equal to the current section's level
294:             lLevel = lLineArguments[0][0].to_i
295:             lLastLevel = lHighestLevelSections[K_Default_Category]
296:             if (lLastLevel == nil)
297:               lLastLevel = 0
298:             end
299:             if (lLevel <= lLastLevel)
300:               warning("#{iFileName}:#{lLineNumber}: This line can never be activated as it is part of a level section of level #{lLastLevel}: #{lLineStripped}")
301:             end
302:             if ((lLevelingSection == nil) and 
303:                 ($RCLLevels[K_Default_Category] >= lLevel))
304:               lFoundUsefulLVLMacro = true
305:               lOutputLine = "#{lLineArguments[0][1]}\n"
306:             end
307:           end
308:         elsif (lLineStripped[0..10] == '#__LVLCAT__')
309:           #puts '----- Match LVLCAT'
310:           lLineArguments = lLineStripped.scan(/^#__LVLCAT__ ([^ ]+) ([0-9]*) (.*)$/)
311:           if (lLineArguments.size != 1)
312:             warning("#{iFileName}:#{lLineNumber}: Malformed line: #{lLineStripped}")
313:             lOutputLine = "# !!! Malformed line: #{lLineStripped}\n"
314:           else
315:             #puts "----- Matched: #{lLineArguments.inspect}"
316:             # Check that the level of this line is greater or equal to the current section's level
317:             lCategory = lLineArguments[0][0]
318:             lLevel = lLineArguments[0][1].to_i
319:             lLastLevel = lHighestLevelSections[lCategory]
320:             if (lLastLevel == nil)
321:               lLastLevel = 0
322:             end
323:             #puts "----- Last level of category #{lCategory}: #{lLastLevel}"
324:             #puts "----- lLevelingSection=#{lLevelingSection.inspect}"
325:             if (lLevel <= lLastLevel)
326:               warning("#{iFileName}:#{lLineNumber}: This line can never be activated as it is part of a level section of level #{lLastLevel}: #{lLineStripped}")
327:             end
328:             if ((lLevelingSection == nil) and
329:                 ($RCLLevels[lCategory] != nil) and
330:                 ($RCLLevels[lCategory] >= lLevel))
331:               lFoundUsefulLVLMacro = true
332:               lOutputLine = "#{lLineArguments[0][2]}\n"
333:             end
334:           end
335:         elsif (lLineStripped[0..11] == '#__LVLRUBY__')
336:           lLineArguments = lLineStripped.scan(/^#__LVLRUBY__ (.*) ### (.*)$/)
337:           if (lLineArguments.size != 1)
338:             warning("#{iFileName}:#{lLineNumber}: Malformed line: #{lLineStripped}")
339:             lOutputLine = "# !!! Malformed line: #{lLineStripped}\n"
340:           else
341:             if ((lLevelingSection == nil) and
342:                 (eval(lLineArguments[0][0])))
343:               lFoundUsefulLVLMacro = true
344:               lOutputLine = "#{lLineArguments[0][1]}\n"
345:             end
346:           end
347:         elsif (lLineStripped[0..12] == '#__LVLBEGIN__')
348:           lLineArguments = lLineStripped.scan(/^#__LVLBEGIN__ ([0-9]*)$/)
349:           if (lLineArguments.size != 1)
350:             warning("#{iFileName}:#{lLineNumber}: Malformed line: #{lLineStripped}")
351:             lOutputLine = "# !!! Malformed line: #{lLineStripped}\n"
352:           else
353:             lLevel = lLineArguments[0][0].to_i
354:             lLastLevel = lHighestLevelSections[K_Default_Category]
355:             if (lLastLevel == nil)
356:               lLastLevel = 0
357:             end
358:             if (lLevel <= lLastLevel)
359:               warning("#{iFileName}:#{lLineNumber}: This level section can never be activated as it is part of a level section of level #{lLastLevel}: #{lLineStripped}")
360:               lOutputLine = "# !!! This level section is useless as it is part of a level section of level #{lLastLevel}: #{lLineStripped}\n"
361:             end
362:             lLevelSections.push([K_Default_Category,lLevel])
363:             if ((lHighestLevelSections[K_Default_Category] == nil) or
364:                 (lHighestLevelSections[K_Default_Category] < lLevel))
365:               lHighestLevelSections[K_Default_Category] = lLevel
366:             end
367:             lReevaluateLevelingSection = true
368:           end
369:         elsif (lLineStripped[0..15] == '#__LVLCATBEGIN__')
370:           lLineArguments = lLineStripped.scan(/^#__LVLCATBEGIN__ ([^ ]+) ([0-9]*)$/)
371:           if (lLineArguments.size != 1)
372:             warning("#{iFileName}:#{lLineNumber}: Malformed line: #{lLineStripped}")
373:             lOutputLine = "# !!! Malformed line: #{lLineStripped}\n"
374:           else
375:             lCategory = lLineArguments[0][0]
376:             lLevel = lLineArguments[0][1].to_i
377:             lLastLevel = lHighestLevelSections[lCategory]
378:             if (lLastLevel == nil)
379:               lLastLevel = 0
380:             end
381:             if (lLevel <= lLastLevel)
382:               warning("#{iFileName}:#{lLineNumber}: This level section can never be activated as it is part of a category level section of level #{lLastLevel}: #{lLineStripped}")
383:               lOutputLine = "# !!! This level section is useless as it is part of a category level section of level #{lLastLevel}: #{lLineStripped}\n"
384:             end
385:             lLevelSections.push([lCategory,lLevel])
386:             if ((lHighestLevelSections[lCategory] == nil) or 
387:                 (lHighestLevelSections[lCategory] < lLevel))
388:               lHighestLevelSections[lCategory] = lLevel
389:             end
390:             # Check if we can output following source code
391:             if ($RCLLevels[lCategory] == nil)
392:               $RCLLevels[lCategory] = 0
393:             end
394:             lReevaluateLevelingSection = true
395:           end
396:         elsif (lLineStripped[0..16] == '#__LVLRUBYBEGIN__')
397:           lLineArguments = lLineStripped.scan(/^#__LVLRUBYBEGIN__ (.*)$/)
398:           if (lLineArguments.size != 1)
399:             warning("#{iFileName}:#{lLineNumber}: Malformed line: #{lLineStripped}")
400:             lOutputLine = "# !!! Malformed line: #{lLineStripped}\n"
401:           else
402:             # Create a unique category for this section
403:             lCategory = "#{K_Ruby_Category} #{lLineNumber}"
404:             lRubyCode = lLineArguments[0][0]
405:             # Set its level to 1
406:             lLevelSections.push([lCategory,1])
407:             lHighestLevelSections[lCategory] = 1
408:             # Check if we can output following source code
409:             if (eval(lRubyCode))
410:               # Activate it
411:               $RCLLevels[lCategory] = 1
412:             else
413:               # Do not activate it
414:               $RCLLevels[lCategory] = 0
415:             end
416:             lReevaluateLevelingSection = true
417:           end
418:         elsif (lLineStripped == '#__LVLEND__')
419:           if (lLevelSections.size > 0)
420:             lCategory, lLevel = lLevelSections.pop
421:             # Recompute the highest level for lCategory
422:             lNewHighestLevel = 0
423:             lLevelSections.each do |iLevelSectionInfo|
424:               if ((iLevelSectionInfo[0] == lCategory) and
425:                   (iLevelSectionInfo[1] > lNewHighestLevel))
426:                 lNewHighestLevel = iLevelSectionInfo[1]
427:               end
428:             end
429:             if (lNewHighestLevel > 0)
430:               lHighestLevelSections[lCategory] = lNewHighestLevel
431:             else
432:               lHighestLevelSections.delete(lCategory)
433:             end
434:             lReevaluateLevelingSection = true
435:           else
436:             warning("#{iFileName}:#{lLineNumber}: Closing level section that was not opened.")
437:             lOutputLine = "# !!! Closing level section that was not opened: #{lLineStripped}\n"
438:           end
439:         end
440:         if (lReevaluateLevelingSection)
441:           # Check if we can output following source code
442:           lLevelingSection = nil
443:           $RCLLevels.each do |iCategory, iLevel|
444:             lLastLevel = lHighestLevelSections[iCategory]
445:             if (lLastLevel == nil)
446:               lLastLevel = 0
447:             end
448:             if (iLevel < lLastLevel)
449:               lLevelingSection = [ iCategory, lLastLevel ]
450:               break
451:             end
452:           end
453:         end
454:         lNewFileContents << lOutputLine
455:         lLineNumber += 1
456:       end
457:     end
458:     # Test that level sections were all terminated correctly
459:     if ((lFoundUsefulLVLMacro) and
460:         (lLevelSections.size > 0))
461:       warning("#{iFileName}: Level sections were not closed properly: #{lLevelSections.size} sections are still opened. It is very unlikely that source code could run.")
462:       lNewFileContents << "# !!! Level sections were not closed properly: #{lLevelSections.size} sections are still opened. It is very unlikely that source code could run: #{lLevelSections.join(', ')}\n"
463:     end
464:     if (iOutputFileName != nil)
465:       # Create the directory if needed
466:       FileUtils::mkdir_p(File.dirname(iOutputFileName))
467:       # Write the file
468:       File.open(iOutputFileName, 'w+') do |iNewFile|
469:         iNewFile.write(lNewFileContents)
470:       end
471:     end
472:     
473:     return lNewFileContents, lFoundUsefulLVLMacro
474:   end
warning(iMessage) click to toggle source

Issue a warning specific to RCodeLeveler Parameters:

  iMessage (String): The message to output
     # File lib/rcodeleveler.rb, line 184
184:   def RCodeLeveler.warning(iMessage)
185:     if ($RCLWarningSeverity == 1)
186:       $stderr.puts "RCodeLeveler - warning: #{iMessage}"
187:     elsif ($RCLWarningSeverity == 2)
188:       raise ParseError, "RCodeLeveler - warning: #{iMessage}"
189:     end
190:   end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.