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
msg
colored 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
msg
as an ANSI-colored debugging message (yellow on blue). -
.divider(length = 75) ⇒ Object
(also: writeLine)
Output a divider made up of
length
hyphen characters. -
.editInPlace(file) ⇒ Object
Open a file and filter each of its lines through the given block a
line
at a time. -
.errorMessage(msg) ⇒ Object
Output the specified
msg
as an ANSI-colored error message (white on red). -
.extractNextVersionFromTags(file) ⇒ Object
Using the CVS log for the given
file
attempt 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
progname
in the user’sPATH
, and return the full path to it, ornil
if 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
msg
as a ANSI-colored program/section header (white on blue). -
.message(msg) ⇒ Object
Output
msg
to STDERR and flush it. -
.prompt(promptString) ⇒ Object
Output the specified
promptString
as 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
promptString
via #prompt, substituting the givendefault
if 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
msg
instead. -
.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
filelist
like that returned by #readManifest, remove the entries therein which match the Regexp objects in the givenantimanifest
and 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 |