Module: Hoe::RakeHelpers

Included in:
Mercurial, MercurialHelpers
Defined in:
lib/hoe/mercurial.rb

Overview

Prompting, command-execution, and other utility functions

Constant Summary collapse

DEFAULT_EDITOR =

The editor to invoke if ENV and ENV aren’t set.

'vi'
ANSI_ATTRIBUTES =

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
}
MULTILINE_PROMPT =

Prompt for multiline input

<<-'EOF'
Enter one or more values for '%s'.
A blank line finishes input.
EOF
CLEAR_TO_EOL =

ANSI escapes for clearing to the end of the line and the entire line

"\e[K"
CLEAR_CURRENT_LINE =
"\e[2K"

Class Method Summary collapse

Class Method Details

.ansi_code(*attributes) ⇒ Object

Create a string that contains the ANSI codes specified and return it



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/hoe/mercurial.rb', line 67

def ansi_code( *attributes )
	attributes.flatten!
	attributes.collect! {|at| at.to_s }
	# $stderr.puts "Returning ansicode for TERM = %p: %p" %
	#		[ ENV['TERM'], attributes ]
	return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
	attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')

	# $stderr.puts "	attr is: %p" % [attributes]
	if attributes.empty?
		return ''
	else
		return "\e[%sm" % attributes
	end
end

.ask_for_confirmation(description, abort_on_decline = true) ⇒ Object Also known as: prompt_for_confirmation

Display a description of a potentially-dangerous task, and prompt for confirmation. If the user answers with anything that begins with ‘y’, yield to the block. If abort_on_decline is true, any non-‘y’ answer will fail with an error message.



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/hoe/mercurial.rb', line 194

def ask_for_confirmation( description, abort_on_decline=true )
	prompt = 'Continue?'

	# If the description looks like a question, use it for the prompt. Otherwise,
	# print it out and
	if description.strip.rindex( '?' )
		prompt = description
	else
		log description
	end

	answer = prompt_with_default( prompt, 'n' ) do |input|
		input =~ /^[yn]/i
	end

	if answer =~ /^y/i
		return yield
	elsif abort_on_decline
		error "Aborted."
		fail
	end

	return false
end

.colorize(*args) ⇒ Object

Colorize the given string with the specified attributes and return it, handling line-endings, color reset, etc.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/hoe/mercurial.rb', line 86

def colorize( *args )
	string = ''

	if block_given?
		string = yield
	else
		string = args.shift
	end

	ending = string[/(\s)$/] || ''
	string = string.rstrip

	return ansi_code( args.flatten ) + string + ansi_code( 'reset' ) + ending
end

.edit(filename) ⇒ Object

Invoke the user’s editor on the given filename and return the exit code from doing so.



266
267
268
269
270
271
272
# File 'lib/hoe/mercurial.rb', line 266

def edit( filename )
	editor = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
	system editor, filename
	unless $?.success? || editor =~ /vim/i
		fail "Editor exited uncleanly."
	end
end

.error_message(msg, details = '') ⇒ Object Also known as: error

Output the specified msg as an ANSI-colored error message (white on red).



104
105
106
# File 'lib/hoe/mercurial.rb', line 104

def error_message( msg, details='' )
	$stderr.puts colorize( 'bold', 'white', 'on_red' ) { msg } + details
end

.get_target_argsObject

Extract all the non Rake-target arguments from ARGV and return them.



286
287
288
289
# File 'lib/hoe/mercurial.rb', line 286

def get_target_args
	args = ARGV.reject {|arg| arg =~ /^-/ || Rake::Task.task_defined?(arg) }
	return args
end

.humanize_file_list(list, indent = FILE_INDENT) ⇒ Object

Returns a human-scannable file list by joining and truncating the list if it’s too long.



293
294
295
296
297
298
299
300
# File 'lib/hoe/mercurial.rb', line 293

def humanize_file_list( list, indent=FILE_INDENT )
	listtext = list[0..5].join( "\n#{indent}" )
	if list.length > 5
		listtext << " (and %d other/s)" % [ list.length - 5 ]
	end

	return listtext
end

.log(*msg) ⇒ Object

Output a logging message



222
223
224
225
# File 'lib/hoe/mercurial.rb', line 222

def log( *msg )
	output = colorize( msg.flatten.join(' '), 'cyan' )
	$stderr.puts( output )
end

.make_prompt_string(string) ⇒ Object

Make a prompt string that will always appear flush left.



111
112
113
# File 'lib/hoe/mercurial.rb', line 111

def make_prompt_string( string )
	return CLEAR_CURRENT_LINE + colorize( 'bold', 'green' ) { string + ' ' }
end

.prompt(prompt_string, failure_msg = "Try again.") ⇒ Object

Output the specified prompt_string as a prompt (in green) and return the user’s input with leading and trailing spaces removed. If a test is provided, the prompt will repeat until the test returns true. An optional failure message can also be passed in.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/hoe/mercurial.rb', line 120

def prompt( prompt_string, failure_msg="Try again." ) # :yields: response
	prompt_string.chomp!
	prompt_string << ":" unless /\W$/.match( prompt_string )
	response = nil

	begin
		prompt = make_prompt_string( prompt_string )
		response = readline( prompt ) || ''
		response.strip!
		if block_given? && ! yield( response )
			error_message( failure_msg + "\n\n" )
			response = nil
		end
	end while response.nil?

	return response
end

.prompt_for_multiple_values(label, default = nil) ⇒ Object

Prompt for an array of values



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/hoe/mercurial.rb', line 168

def prompt_for_multiple_values( label, default=nil )
	$stderr.puts( MULTILINE_PROMPT % [label] )
	if default
		$stderr.puts "Enter a single blank line to keep the default:\n	%p" % [ default ]
	end

	results = []
	result = nil

	begin
		result = readline( make_prompt_string("> ") )
		if result.nil? || result.empty?
			results << default if default && results.empty?
		else
			results << result
		end
	end until result.nil? || result.empty?

	return results.flatten
end

.prompt_with_default(prompt_string, default, failure_msg = "Try again.") ⇒ Object

Prompt the user with the given prompt_string via #prompt, substituting the given default if the user doesn’t input anything. If a test is provided, the prompt will repeat until the test returns true. An optional failure message can also be passed in.



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/hoe/mercurial.rb', line 143

def prompt_with_default( prompt_string, default, failure_msg="Try again." )
	response = nil

	begin
		default ||= '~'
		response = prompt( "%s [%s]" % [ prompt_string, default ] )
		response = default.to_s if !response.nil? && response.empty?

		trace "Validating response %p" % [ response ]

		# the block is a validator.	 We need to make sure that the user didn't
		# enter '~', because if they did, it's nil and we should move on.	 If
		# they didn't, then call the block.
		if block_given? && response != '~' && ! yield( response )
			error_message( failure_msg + "\n\n" )
			response = nil
		end
	end while response.nil?

	return nil if response == '~'
	return response
end

.quotelist(*args) ⇒ Object

Return the specified args as a string, quoting any that have a space.



237
238
239
# File 'lib/hoe/mercurial.rb', line 237

def quotelist( *args )
	return args.flatten.collect {|part| part =~ /\s/ ? part.inspect : part}
end

.read_command_output(cmd, *args) ⇒ Object

Run the given cmd with the specified args without interpolation by the shell and return anything written to its STDOUT.



277
278
279
280
281
282
# File 'lib/hoe/mercurial.rb', line 277

def read_command_output( cmd, *args )
	# output = IO.read( '|-' ) or exec cmd, *args # No popen on some platforms. :(
	argstr = Shellwords.join( args )
	output = `#{cmd} #{argstr}`.chomp
	return output
end

.run(*cmd) ⇒ Object

Run the specified command cmd with system(), failing if the execution fails. Doesn’t invoke a subshell (unlike ‘sh’).



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/hoe/mercurial.rb', line 244

def run( *cmd )
	cmd.flatten!

	if cmd.length > 1
		trace( "Running:", quotelist(*cmd) )
	else
		trace( "Running:", cmd )
	end

	if Rake.application.options.dryrun
		log "(dry run mode)"
	else
		system( *cmd )
		unless $?.success?
			fail "Command failed: [%s]" % [cmd.join(' ')]
		end
	end
end

.trace(*msg) ⇒ Object

Output a logging message if tracing is on



229
230
231
232
233
# File 'lib/hoe/mercurial.rb', line 229

def trace( *msg )
	return unless Rake.application.options.trace
	output = colorize( msg.flatten.join(' '), 'yellow' )
	$stderr.puts( output )
end