blob: a704ec7a374786578da08f4c482d95dc9f3d6ab8 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with this
# work for additional information regarding copyright ownership. The ASF
# licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
module Buildr #nodoc
# A utility class that helps with colorizing output for interactive shells where appropriate
class Console
class << self
def use_color
@use_color.nil? ? false : @use_color
end
def use_color=(use_color)
return if use_color && !setup_support
@use_color = use_color
end
# Emit message with color at the start of the message and the clear color command at the end of the sequence.
def color(message, color)
raise "Unknown color #{color.inspect}" unless [:green, :red, :blue].include?(color)
return message unless use_color
constants = {:green => "\e[32m", :red => "\e[31m", :blue => "\e[34m"}
@java_console.putString("#{constants[color]}#{message}\e[0m") if @java_console
"#{constants[color]}#{message}\e[0m"
end
# Return the [rows, columns] of a console or nil if unknown
def console_dimensions
return nil unless setup_support
begin
if Buildr::Util.win_os?
if Buildr::Util.java_platform?
if JRUBY_VERSION =~ /^1.7/
[@java_terminal.get_width, @java_terminal.get_height]
else
[@java_terminal.getTerminalWidth, @java_terminal.getTerminalHeight]
end
else
Win32::Console.new(Win32::Console::STD_OUTPUT_HANDLE).MaxWindow
end
elsif $stdout.isatty
if /solaris/ =~ RUBY_PLATFORM and
`stty` =~ /\brows = (\d+).*\bcolumns = (\d+)/
[$2, $1].map { |c| x.to_i }
else
`stty size 2> /dev/null`.split.map { |x| x.to_i }.reverse
end
else
nil
end
rescue => e
nil
end
end
# Return the number of columns in console or nil if unknown
def output_cols
d = console_dimensions
d ? d[0] : nil
end
def agree?(message)
puts "#{message} (Y or N)"
:agree == ask('Y' => :agree, 'N' => :disagree)
end
def ask_password(prompt)
puts prompt
begin
set_no_echo_mode
password = $stdin.readline
return password.chomp
ensure
reset_mode
end
end
def present_menu(header, options)
puts header
question_options = {}
count = 1
options.each_pair do |message, result|
puts "#{count}. #{message}"
question_options[count.to_s] = result
count += 1
end
ask(question_options)
end
private
def set_no_echo_mode
return unless setup_support
if Buildr::Util.win_os?
if Buildr::Util.java_platform?
if @java_console
@state = @java_console.getEchoCharacter
@java_console.setEchoCharacter 0
end
else
c = Win32::Console.new(Win32::Console::STD_OUTPUT_HANDLE)
c.Echo(false) rescue Exception
end
else
@state = `stty -g 2>/dev/null`
`stty -echo -icanon 2>/dev/null`
end
end
def reset_mode
return unless setup_support
if Buildr::Util.win_os?
if Buildr::Util.java_platform?
if @java_console
@java_console.setEchoCharacter @state
end
else
c = Win32::Console.new(Win32::Console::STD_OUTPUT_HANDLE)
c.Echo(true) rescue Exception
end
else
`stty #{@state} 2>/dev/null`
end
@state = nil
end
def ask(options)
keys = options.keys
keys_downcased = keys.collect { |k| k.downcase }
result = nil
show_prompt = false
until keys_downcased.include?(result)
puts "Invalid response. Valid responses include: #{keys.join(', ')}\n" if show_prompt
show_prompt = true
result = $stdin.readline
result = result.strip.downcase if result
end
options.each_pair do |key, value|
if key.downcase == result
return value.is_a?(Proc) ? value.call : value
end
end
return nil
end
def setup_support
return @initialized unless @initialized.nil?
@initialized = false
begin
if Buildr::Util.win_os?
if Buildr::Util.java_platform?
require 'java'
require 'readline'
begin
# Attempt jline1
java_import 'java.io.OutputStreamWriter'
java_import 'java.nio.channels.Channels'
java_import 'jline.ConsoleReader'
java_import 'jline.Terminal'
@java_input = Java::JavaNioChannels::Channels.newInputStream($stdin.to_channel)
@java_output = Java::JavaIo.OutputStreamWriter.new(Java::JavaNioChannels::Channels.newOutputStream($stdout.to_channel))
@java_terminal = Java::Jline::Terminal.getTerminal
@java_console = Java::Jline::ConsoleReader.new(@java_input, @java_output)
@java_console.setUseHistory(false)
@java_console.set_bell_enabled(true)
@java_console.setUsePagination(false)
rescue Exception
# attempt jline 2
java_import 'jline.console.ConsoleReader'
@java_console = ConsoleReader.new($stdin.to_inputstream, $stdout.to_outputstream)
@java_console.set_history_enabled(false)
@java_console.set_bell_enabled(true)
@java_console.set_pagination_enabled(false)
@java_terminal = @java_console.getTerminal
end
return false
else
require 'Win32/Console/ANSI'
end
end
rescue
# Unfortunately we have multiple incompatible jline libraries
# in the classpath. This is probably because we are using jruby
# 1.7.5 with a library like scala and both use incompatible jline
# implementations
return false
rescue NameError
return false
rescue LoadError
return false
end
@initialized = true
return true
end
end
end
end
Buildr::Console.use_color = $stdout.isatty