Module: UtilityFunctions
- Defined in:
- lib/linkparser/utils.rb
Constant Summary collapse
- ANTIMANIFEST =
The list of regexen that eliminate files from the MANIFEST
[ /makedist\.rb/, /\bCVS\b/, /~$/, /^#/, %r{docs/html}, %r{docs/man}, /^TEMPLATE/, /\.cvsignore/, /\.s?o$/ ]
- AnsiAttributes =
Set some ANSI escape code constants (Shamelessly stolen from Perl’s Term::ANSIColor by Russ Allbery <[email protected]> and Zenin <[email protected]>
{ 'clear' => 0, 'reset' => 0, 'bold' => 1, 'dark' => 2, 'underline' => 4, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'concealed' => 8, 'black' => 30, 'on_black' => 40, 'red' => 31, 'on_red' => 41, 'green' => 32, 'on_green' => 42, 'yellow' => 33, 'on_yellow' => 43, 'blue' => 34, 'on_blue' => 44, 'magenta' => 35, 'on_magenta' => 45, 'cyan' => 36, 'on_cyan' => 46, 'white' => 37, 'on_white' => 47 }
- ErasePreviousLine =
"\033[A\033[K"
Class Method Summary collapse
-
.abort(msg) ⇒ Object
Output the specified
msgcolored in ANSI red and exit with a status of 1. -
.ansiCode(*attributes) ⇒ Object
Create a string that contains the ANSI codes specified and return it.
-
.debugMsg(msg) ⇒ Object
Output the specified
msgas an ANSI-colored debugging message (yellow on blue). -
.divider(length = 75) ⇒ Object
(also: writeLine)
Output a divider made up of
lengthhyphen characters. -
.editInPlace(file) ⇒ Object
Open a file and filter each of its lines through the given block a
lineat a time. -
.errorMessage(msg) ⇒ Object
Output the specified
msgas an ANSI-colored error message (white on red). -
.extractNextVersionFromTags(file) ⇒ Object
Using the CVS log for the given
fileattempt to guess what the next release version might be. -
.extractProjectName ⇒ Object
Extract the project name (CVS Repository name) for the given directory.
-
.findProgram(progname) ⇒ Object
Search for the program specified by the given
prognamein the user’sPATH, and return the full path to it, ornilif no such program is in the path. -
.findRdocableFiles(catalogFile = "docs/CATALOG") ⇒ Object
Given a documentation
catalogFile, which is in the same format as that described by #readManifest, read and expand it, and then return a list of those files which appear to have RDoc documentation in them. -
.getVettedManifest(manifestFile = "MANIFEST", antimanifest = ANTIMANIFEST) ⇒ Object
Combine a call to #readManifest with one to #vetManifest.
-
.header(msg) ⇒ Object
Output
msgas a ANSI-colored program/section header (white on blue). -
.message(msg) ⇒ Object
Output
msgto STDERR and flush it. -
.prompt(promptString) ⇒ Object
Output the specified
promptStringas a prompt (in green) and return the user’s input with leading and trailing spaces removed. -
.promptWithDefault(promptString, default) ⇒ Object
Prompt the user with the given
promptStringvia #prompt, substituting the givendefaultif the user doesn’t input anything. -
.readManifest(manifestFile = "MANIFEST") ⇒ Object
Read the specified
manifestFile, which is a text file describing which files to package up for a distribution. -
.replaceMessage(msg) ⇒ Object
Erase the previous line (if supported by your terminal) and output the specified
msginstead. -
.shellCommand(*command) ⇒ Object
Execute the specified shell
command, read the results, and return them. -
.testForLibrary(library, nicename = nil) ⇒ Object
Test for the presence of the specified
library, and output a message describing the test usingnicename. -
.testForRequiredLibrary(library, nicename = nil, raaUrl = nil, downloadUrl = nil, fatal = true) ⇒ Object
Test for the presence of the specified
library, and output a message describing the problem usingnicename. -
.vetManifest(filelist, antimanifest = ANITMANIFEST) ⇒ Object
Given a
filelistlike that returned by #readManifest, remove the entries therein which match the Regexp objects in the givenantimanifestand return the resultant Array.
Class Method Details
.abort(msg) ⇒ Object
Output the specified msg colored in ANSI red and exit with a status of 1.
357 358 359 360 |
# File 'lib/linkparser/utils.rb', line 357 def abort( msg ) print ansiCode( 'bold', 'red' ) + "Aborted: " + msg.chomp + ansiCode( 'reset' ) + "\n\n" Kernel.exit!( 1 ) end |
.ansiCode(*attributes) ⇒ Object
Create a string that contains the ANSI codes specified and return it
267 268 269 270 271 272 273 274 |
# File 'lib/linkparser/utils.rb', line 267 def ansiCode( *attributes ) attr = attributes.collect {|a| AnsiAttributes[a] ? AnsiAttributes[a] : nil}.compact.join(';') if attr.empty? return '' else return "\e[%sm" % attr end end |
.debugMsg(msg) ⇒ Object
Output the specified msg as an ANSI-colored debugging message (yellow on blue).
335 336 337 338 339 340 |
# File 'lib/linkparser/utils.rb', line 335 def debugMsg( msg ) return unless $DEBUG msg.chomp! $stderr.puts ansiCode( 'bold', 'yellow', 'on_blue' ) + ">>> #{msg}" + ansiCode( 'reset' ) $stderr.flush end |
.divider(length = 75) ⇒ Object Also known as: writeLine
Output a divider made up of length hyphen characters.
350 351 352 |
# File 'lib/linkparser/utils.rb', line 350 def divider( length=75 ) puts "\r" + ("-" * length ) end |
.editInPlace(file) ⇒ Object
Open a file and filter each of its lines through the given block a line at a time. The return value of the block is used as the new line, or omitted if the block returns nil or false.
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 |
# File 'lib/linkparser/utils.rb', line 510 def editInPlace( file ) # :yields: line raise "No block specified for editing operation" unless block_given? tempName = "#{file}.#{$$}" File::open( tempName, File::RDWR|File::CREAT, 0600 ) {|tempfile| File::unlink( tempName ) File::open( file, File::RDONLY ) {|fh| fh.each {|line| newline = yield( line ) or next tempfile.print( newline ) } } tempfile.seek(0) File::open( file, File::TRUNC|File::WRONLY, 0644 ) {|newfile| newfile.print( tempfile.read ) } } end |
.errorMessage(msg) ⇒ Object
Output the specified msg as an ANSI-colored error message (white on red).
329 330 331 |
# File 'lib/linkparser/utils.rb', line 329 def errorMessage( msg ) ansiCode( 'bold', 'white', 'on_red' ) + msg + ansiCode( 'reset' ) end |
.extractNextVersionFromTags(file) ⇒ Object
Using the CVS log for the given file attempt to guess what the next release version might be. This only works if releases are tagged with tags like ‘RELEASE_x_y’.
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 |
# File 'lib/linkparser/utils.rb', line 395 def extractNextVersionFromTags( file ) "Attempting to extract next release version from CVS tags for #{file}...\n" raise RuntimeError, "No such file '#{file}'" unless File.exists?( file ) cvsPath = findProgram( 'cvs' ) or raise RuntimeError, "Cannot find the 'cvs' program. Aborting." output = %x{#{cvsPath} log #{file}} release = [ 0, 0 ] output.scan( /RELEASE_(\d+)_(\d+)/ ) {|match| if $1.to_i > release[0] || $2.to_i > release[1] release = [ $1.to_i, $2.to_i ] replaceMessage( "Found %d.%02d...\n" % release ) end } if release[1] >= 99 release[0] += 1 release[1] = 1 else release[1] += 1 end return "%d.%02d" % release end |
.extractProjectName ⇒ Object
Extract the project name (CVS Repository name) for the given directory.
421 422 423 |
# File 'lib/linkparser/utils.rb', line 421 def extractProjectName File.open( "CVS/Repository", "r").readline.chomp end |
.findProgram(progname) ⇒ Object
Search for the program specified by the given progname in the user’s PATH, and return the full path to it, or nil if no such program is in the path.
384 385 386 387 388 389 390 |
# File 'lib/linkparser/utils.rb', line 384 def findProgram( progname ) ENV['PATH'].split(File::PATH_SEPARATOR).each {|d| file = File.join( d, progname ) return file if File.executable?( file ) } return nil end |
.findRdocableFiles(catalogFile = "docs/CATALOG") ⇒ Object
Given a documentation catalogFile, which is in the same format as that described by #readManifest, read and expand it, and then return a list of those files which appear to have RDoc documentation in them. If catalogFile is nil or does not exist, the MANIFEST file is used instead.
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 |
# File 'lib/linkparser/utils.rb', line 478 def findRdocableFiles( catalogFile="docs/CATALOG" ) startlist = [] if File.exists? catalogFile "Using CATALOG file (%s).\n" % catalogFile startlist = getVettedManifest( catalogFile ) else "Using default MANIFEST\n" startlist = getVettedManifest() end "Looking for RDoc comments in:\n" if $VERBOSE startlist.select {|fn| " #{fn}: " if $VERBOSE found = false File::open( fn, "r" ) {|fh| fh.each {|line| if line =~ /^(\s*#)?\s*=/ || line =~ /:\w+:/ || line =~ %r{/\*} found = true break end } } ( (found ? "yes" : "no") + "\n" ) if $VERBOSE found } end |
.getVettedManifest(manifestFile = "MANIFEST", antimanifest = ANTIMANIFEST) ⇒ Object
Combine a call to #readManifest with one to #vetManifest.
469 470 471 |
# File 'lib/linkparser/utils.rb', line 469 def getVettedManifest( manifestFile="MANIFEST", antimanifest=ANTIMANIFEST ) vetManifest( readManifest(manifestFile), antimanifest ) end |
.header(msg) ⇒ Object
Output msg as a ANSI-colored program/section header (white on blue).
315 316 317 318 319 |
# File 'lib/linkparser/utils.rb', line 315 def header( msg ) msg.chomp! $stderr.puts ansiCode( 'bold', 'white', 'on_blue' ) + msg + ansiCode( 'reset' ) $stderr.flush end |
.message(msg) ⇒ Object
Output msg to STDERR and flush it.
322 323 324 325 |
# File 'lib/linkparser/utils.rb', line 322 def ( msg ) $stderr.print msg $stderr.flush end |
.prompt(promptString) ⇒ Object
Output the specified promptString as a prompt (in green) and return the user’s input with leading and trailing spaces removed.
364 365 366 367 |
# File 'lib/linkparser/utils.rb', line 364 def prompt( promptString ) promptString.chomp! return readline( ansiCode('bold', 'green') + "#{promptString}: " + ansiCode('reset') ).strip end |
.promptWithDefault(promptString, default) ⇒ Object
Prompt the user with the given promptString via #prompt, substituting the given default if the user doesn’t input anything.
372 373 374 375 376 377 378 379 |
# File 'lib/linkparser/utils.rb', line 372 def promptWithDefault( promptString, default ) response = prompt( "%s [%s]" % [ promptString, default ] ) if response.empty? return default else return response end end |
.readManifest(manifestFile = "MANIFEST") ⇒ Object
Read the specified manifestFile, which is a text file describing which files to package up for a distribution. The manifest should consist of one or more lines, each containing one filename or shell glob pattern.
429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 |
# File 'lib/linkparser/utils.rb', line 429 def readManifest( manifestFile="MANIFEST" ) "Building manifest..." raise "Missing #{manifestFile}, please remake it" unless File.exists? manifestFile manifest = IO::readlines( manifestFile ).collect {|line| line.chomp }.select {|line| line !~ /^(\s*(#.*)?)?$/ } filelist = [] for pat in manifest $stderr.puts "Adding files that match '#{pat}' to the file list" if $VERBOSE filelist |= Dir.glob( pat ).find_all {|f| FileTest.file?(f)} end "found #{filelist.length} files.\n" return filelist end |
.replaceMessage(msg) ⇒ Object
Erase the previous line (if supported by your terminal) and output the specified msg instead.
344 345 346 347 |
# File 'lib/linkparser/utils.rb', line 344 def replaceMessage( msg ) print ErasePreviousLine ( msg ) end |
.shellCommand(*command) ⇒ Object
Execute the specified shell command, read the results, and return them. Like a %x{} that returns an Array instead of a String.
533 534 535 536 537 538 |
# File 'lib/linkparser/utils.rb', line 533 def shellCommand( *command ) raise "Empty command" if command.empty? cmdpipe = IO::popen( command.join(' '), 'r' ) return cmdpipe.readlines end |
.testForLibrary(library, nicename = nil) ⇒ Object
Test for the presence of the specified library, and output a message describing the test using nicename. If nicename is nil, the value in library is used to build a default.
279 280 281 282 283 284 285 286 287 288 289 |
# File 'lib/linkparser/utils.rb', line 279 def testForLibrary( library, nicename=nil ) nicename ||= library ( "Testing for the #{nicename} library..." ) if $:.detect {|dir| File.exists?(File.join(dir,"#{library}.rb")) || File.exists?(File.join(dir,"#{library}.so"))} ( "found.\n" ) return true else ( "not found.\n" ) return false end end |
.testForRequiredLibrary(library, nicename = nil, raaUrl = nil, downloadUrl = nil, fatal = true) ⇒ Object
Test for the presence of the specified library, and output a message describing the problem using nicename. If nicename is nil, the value in library is used to build a default. If raaUrl and/or downloadUrl are specified, they are also use to build a message describing how to find the required library. If fatal is true, a missing library will cause the program to abort.
298 299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/linkparser/utils.rb', line 298 def testForRequiredLibrary( library, nicename=nil, raaUrl=nil, downloadUrl=nil, fatal=true ) nicename ||= library unless testForLibrary( library, nicename ) msgs = [ "You are missing the required #{nicename} library.\n" ] msgs << "RAA: #{raaUrl}\n" if raaUrl msgs << "Download: #{downloadUrl}\n" if downloadUrl if fatal abort msgs.join('') else errorMessage msgs.join('') end end return true end |
.vetManifest(filelist, antimanifest = ANITMANIFEST) ⇒ Object
Given a filelist like that returned by #readManifest, remove the entries therein which match the Regexp objects in the given antimanifest and return the resultant Array.
452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 |
# File 'lib/linkparser/utils.rb', line 452 def vetManifest( filelist, antimanifest=ANITMANIFEST ) origLength = filelist.length "Vetting manifest..." for regex in antimanifest if $VERBOSE "\n\tPattern /#{regex.source}/ removed: " + filelist.find_all {|file| regex.match(file)}.join(', ') end filelist.delete_if {|file| regex.match(file)} end "removed #{origLength - filelist.length} files from the list.\n" return filelist end |