Module: UtilityFunctions
- Defined in:
- lib/carat-dev/misc/utils.rb
Overview
BEGIN
begin
require 'readline'
include Readline
rescue LoadError => e
$stderr.puts "Faking readline..."
def readline( prompt )
$stderr.print prompt.chomp
return $stdin.gets.chomp
end
end
begin
require 'yaml'
$yaml = true
rescue LoadError => e
$stderr.puts "No YAML; try() will use .inspect instead."
$yaml = false
end
Defined Under Namespace
Modules: RubyLoader
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. -
.ensure_version(ver) ⇒ Object
Ensures that the version number of the installed ruby is greater than or equal to the version string supplied.
-
.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. -
.terse_block(&block) ⇒ Object
Run a block, with $VERBOSE set to false.
-
.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
. -
.try(msg, bind = nil) ⇒ Object
Try the specified code block, printing the given.
-
.verbose_block(v = true, &block) ⇒ Object
Run a block, with $VERBOSE set to v.
-
.verboseOff ⇒ Object
Execute a block with $VERBOSE set to
false
, restoring it to its previous value before returning. -
.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.
193 194 195 196 |
# File 'lib/carat-dev/misc/utils.rb', line 193 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
100 101 102 103 104 105 106 107 108 |
# File 'lib/carat-dev/misc/utils.rb', line 100 def ansiCode( *attributes ) return '' unless /(?:vt10[03]|xterm(?:-color)?|linux)/i =~ ENV['TERM'] 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).
171 172 173 174 175 176 |
# File 'lib/carat-dev/misc/utils.rb', line 171 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.
186 187 188 |
# File 'lib/carat-dev/misc/utils.rb', line 186 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
.
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
# File 'lib/carat-dev/misc/utils.rb', line 346 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 |
.ensure_version(ver) ⇒ Object
Ensures that the version number of the installed ruby is greater than or equal to the version string supplied. Credit to Robert Klemme for posting this on ruby-talk.
ensure_version "1.7.0"
ensure_version "1.8.0"
ensure_version "1.8.1"
452 453 454 455 456 |
# File 'lib/carat-dev/misc/utils.rb', line 452 def ensure_version( ver ) if ( RUBY_VERSION.split(/\./).map{|x|x.to_i} <=> ver.split(/\./).map{|x|x.to_i} ) < 0 throw "Version error: should be #{ver} but is #{RUBY_VERSION}" end end |
.errorMessage(msg) ⇒ Object
Output the specified msg
as an ANSI-colored error message (white on red).
165 166 167 |
# File 'lib/carat-dev/misc/utils.rb', line 165 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’.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/carat-dev/misc/utils.rb', line 231 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.
257 258 259 |
# File 'lib/carat-dev/misc/utils.rb', line 257 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.
220 221 222 223 224 225 226 |
# File 'lib/carat-dev/misc/utils.rb', line 220 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.
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
# File 'lib/carat-dev/misc/utils.rb', line 314 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.
305 306 307 |
# File 'lib/carat-dev/misc/utils.rb', line 305 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).
151 152 153 154 155 |
# File 'lib/carat-dev/misc/utils.rb', line 151 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.
158 159 160 161 |
# File 'lib/carat-dev/misc/utils.rb', line 158 def ( msg ) $stderr.print ansiCode( 'cyan' ) + msg + ansiCode( 'reset' ) $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.
200 201 202 203 |
# File 'lib/carat-dev/misc/utils.rb', line 200 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.
208 209 210 211 212 213 214 215 |
# File 'lib/carat-dev/misc/utils.rb', line 208 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.
265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 |
# File 'lib/carat-dev/misc/utils.rb', line 265 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.
180 181 182 183 |
# File 'lib/carat-dev/misc/utils.rb', line 180 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.
369 370 371 372 373 374 |
# File 'lib/carat-dev/misc/utils.rb', line 369 def shellCommand( *command ) raise "Empty command" if command.empty? cmdpipe = IO::popen( command.join(' '), 'r' ) return cmdpipe.readlines end |
.terse_block(&block) ⇒ Object
Run a block, with $VERBOSE set to false. No other threads will run while this block is being executed.
440 441 442 |
# File 'lib/carat-dev/misc/utils.rb', line 440 def terse_block(&block) verbose_block(false, &block) 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.
113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/carat-dev/misc/utils.rb', line 113 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.
134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/carat-dev/misc/utils.rb', line 134 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 |
.try(msg, bind = nil) ⇒ Object
Try the specified code block, printing the given
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 |
# File 'lib/carat-dev/misc/utils.rb', line 395 def try( msg, bind=nil ) #:yield: result = nil "Trying #{msg}..." begin rval = nil if block_given? rval = yield else file, line = caller(1)[0].split(/:/,2) rval = eval( msg, bind, file, line.to_i ) end if $yaml result = rval.to_yaml else result = rval.inspect end rescue Exception => err nicetrace = err.backtrace.delete_if {|frame| /in `(try|eval)'/ =~ frame }.join("\n\t") result = err. + "\n\t" + nicetrace ensure puts result end end |
.verbose_block(v = true, &block) ⇒ Object
Run a block, with $VERBOSE set to v. No other threads will run while this block is being executed.
426 427 428 429 430 431 432 433 434 435 436 |
# File 'lib/carat-dev/misc/utils.rb', line 426 def verbose_block(v = true, &block) Thread.critical = true tmp = $VERBOSE $VERBOSE = v begin yield ensure $VERBOSE = tmp Thread.critical = false end end |
.verboseOff ⇒ Object
Execute a block with $VERBOSE set to false
, restoring it to its previous value before returning.
378 379 380 381 382 383 384 385 386 387 388 389 390 391 |
# File 'lib/carat-dev/misc/utils.rb', line 378 def verboseOff raise LocalJumpError, "No block given" unless block_given? thrcrit = Thread.critical oldverbose = $VERBOSE begin Thread.critical = true $VERBOSE = false yield ensure $VERBOSE = oldverbose Thread.critical = false end 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.
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/carat-dev/misc/utils.rb', line 288 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 |