Skip to content

Commit

Permalink
Add :active_color, :help_color & :prefix to allow customized themeing…
Browse files Browse the repository at this point in the history
… of prompts and close issue #12
  • Loading branch information
piotrmurach committed Mar 28, 2016
1 parent ea744c1 commit 1bd5c66
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 59 deletions.
13 changes: 13 additions & 0 deletions lib/tty/prompt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,19 @@ class InvalidArgument < ArgumentError; end

# Prompt prefix
#
# @example
# prompt = TTY::Prompt.new(prefix: [?])
#
# @return [String]
#
# @api private
attr_reader :prefix

# Theme colors
#
# @api private
attr_reader :active_color, :help_color, :error_color

def_delegators :@pastel, :decorate, :strip

def_delegators :@cursor, :clear_lines, :clear_line,
Expand All @@ -60,6 +70,9 @@ def initialize(*args)
@input = options.fetch(:input) { $stdin }
@output = options.fetch(:output) { $stdout }
@prefix = options.fetch(:prefix) { '' }
@active_color = options.fetch(:active_color) { :green }
@help_color = options.fetch(:help_color) { :bright_black }
@error_color = options.fetch(:error_color) { :red }

@cursor = TTY::Cursor
@pastel = Pastel.new
Expand Down
6 changes: 3 additions & 3 deletions lib/tty/prompt/confirm_question.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ def call(message, &block)
#
# @api private
def render_question
header = "#{prompt.prefix}#{message} "
header = "#{@prefix}#{message} "

if !@done
header += @prompt.decorate("(#{@suffix})", :bright_black) + ' '
header += @prompt.decorate("(#{@suffix})", @help_color) + ' '
else
answer = convert_result(@input)
label = answer ? @positive : @negative
header += @prompt.decorate(label, @color)
header += @prompt.decorate(label, @active_color)
end
@prompt.print(header)
@prompt.print("\n") if @done
Expand Down
27 changes: 15 additions & 12 deletions lib/tty/prompt/enum_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,17 @@ class EnumList
#
# @api public
def initialize(prompt, options = {})
@prompt = prompt
@done = false
@failure = false
@enum = options.fetch(:enum) { ')' }
@default = options.fetch(:default) { 1 }
@active = @default
@choices = Choices.new
@color = options.fetch(:color) { :green }
@prompt = prompt
@prefix = options.fetch(:prefix) { @prompt.prefix }
@enum = options.fetch(:enum) { ')' }
@default = options.fetch(:default) { 1 }
@active_color = options.fetch(:active_color) { @prompt.active_color }
@help_color = options.fetch(:help_color) { @prompt.help_color }
@error_color = options.fetch(:error_color) { @prompt.error_color }
@done = false
@failure = false
@active = @default
@choices = Choices.new

@prompt.subscribe(self)
end
Expand Down Expand Up @@ -161,7 +164,7 @@ def refresh
#
# @api private
def render_question
header = "#{@prompt.prefix}#{@question} #{render_header}"
header = "#{@prefix}#{@question} #{render_header}"
@prompt.puts(header)
return if @done
@prompt.print(render_menu)
Expand All @@ -172,7 +175,7 @@ def render_question
# @api private
def render_error
error = 'Please enter a valid index'
@prompt.print("\n" + @prompt.decorate('>>', :red) + ' ' + error)
@prompt.print("\n" + @prompt.decorate('>>', @error_color) + ' ' + error)
@prompt.print(@prompt.cursor.prev_line)
@prompt.print(@prompt.cursor.forward(render_footer.size))
end
Expand All @@ -186,7 +189,7 @@ def render_header
return '' unless @done
return '' unless @active
selected_item = "#{@choices[@active - 1].name}"
@prompt.decorate(selected_item, @color)
@prompt.decorate(selected_item, @active_color)
end

# Render footer for the indexed menu
Expand All @@ -209,7 +212,7 @@ def render_menu
num = (index + 1).to_s + @enum + Symbols::SPACE
selected = Symbols::SPACE * 2 + num + choice.name
output << if index + 1 == @active
@prompt.decorate("#{selected}", @color)
@prompt.decorate("#{selected}", @active_color)
else
selected
end
Expand Down
32 changes: 16 additions & 16 deletions lib/tty/prompt/expander.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ class Prompt
#
# @api private
class Expander
attr_reader :default

HELP_CHOICE = {
key: 'h',
name: 'print help',
Expand All @@ -21,15 +19,17 @@ class Expander
#
# @api public
def initialize(prompt, options = {})
@prompt = prompt
@default = options.fetch(:default) { 1 }
@color = options.fetch(:color) { :green }
@choices = Choices.new
@selected = nil
@done = false
@status = :collapsed
@hint = nil
@default_key = false
@prompt = prompt
@prefix = options.fetch(:prefix) { @prompt.prefix }
@default = options.fetch(:default) { 1 }
@active_color = options.fetch(:active_color) { @prompt.active_color }
@help_color = options.fetch(:help_color) { @prompt.help_color }
@choices = Choices.new
@selected = nil
@done = false
@status = :collapsed
@hint = nil
@default_key = false

@prompt.subscribe(self)
end
Expand Down Expand Up @@ -167,15 +167,15 @@ def render_answer
end

def render_header
header = "#{@prompt.prefix}#{@message} "
header = "#{@prefix}#{@message} "

if @done
selected_item = "#{@selected.name}"
header << @prompt.decorate(selected_item, @color)
header << @prompt.decorate(selected_item, @active_color)
elsif collapsed?
help = %[(enter "h" for help) ]
help << "[#{possible_keys}] "
header << @prompt.decorate(help, :bright_black)
header << @prompt.decorate(help, @help_color)
header << @input
end

Expand All @@ -185,7 +185,7 @@ def render_header
# @api private
def render_hint
hint = "\n"
hint << @prompt.decorate('>> ', @color)
hint << @prompt.decorate('>> ', @active_color)
hint << @hint
@prompt.print(hint)
@prompt.print(@prompt.cursor.prev_line)
Expand Down Expand Up @@ -249,7 +249,7 @@ def render_menu
@choices.each do |choice|
chosen = %(#{choice.key} - #{choice.name})
if @selected && @selected.key == choice.key
chosen = @prompt.decorate(chosen, @color)
chosen = @prompt.decorate(chosen, @active_color)
end
output << ' ' + chosen + "\n"
end
Expand Down
16 changes: 9 additions & 7 deletions lib/tty/prompt/list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ class List
# @api public
def initialize(prompt, options = {})
@prompt = prompt
@first_render = true
@done = false
@prefix = options.fetch(:prefix) { @prompt.prefix }
@enum = options.fetch(:enum) { nil }
@default = Array[options.fetch(:default) { 1 }]
@active = @default.first
@choices = Choices.new
@color = options.fetch(:color) { :green }
@active_color = options.fetch(:active_color) { @prompt.active_color }
@help_color = options.fetch(:help_color) { @prompt.help_color }
@marker = options.fetch(:marker) { Symbols::ITEM_SELECTED }
@help = options[:help]
@first_render = true
@done = false

@prompt.subscribe(self)
end
Expand Down Expand Up @@ -197,7 +199,7 @@ def refresh
#
# @api private
def render_question
header = "#{@prompt.prefix}#{@question} #{render_header}"
header = "#{@prefix}#{@question} #{render_header}"
@prompt.puts(header)
@first_render = false
@prompt.print(render_menu) unless @done
Expand All @@ -219,9 +221,9 @@ def help
def render_header
if @done
selected_item = "#{@choices[@active - 1].name}"
@prompt.decorate(selected_item, @color)
@prompt.decorate(selected_item, @active_color)
elsif @first_render
@prompt.decorate(help, :bright_black)
@prompt.decorate(help, @help_color)
end
end

Expand All @@ -234,7 +236,7 @@ def render_menu
num = enumerate? ? (index + 1).to_s + @enum + Symbols::SPACE : ''
message = if index + 1 == @active
selected = @marker + Symbols::SPACE + num + choice.name
@prompt.decorate("#{selected}", @color)
@prompt.decorate("#{selected}", @active_color)
else
Symbols::SPACE * 2 + num + choice.name
end
Expand Down
4 changes: 2 additions & 2 deletions lib/tty/prompt/mask_question.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ def keypress(event)
#
# @api private
def render_question
header = "#{prompt.prefix}#{message} "
header = "#{@prefix}#{message} "
if echo?
masked = "#{@mask * "#{@input}".length}"
if @done_masked && !@failure
masked = @prompt.decorate(masked, @color)
masked = @prompt.decorate(masked, @active_color)
end
header += masked
end
Expand Down
4 changes: 2 additions & 2 deletions lib/tty/prompt/multi_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def selected_names
def render_header
instructions = @prompt.decorate(help, :bright_black)
if @done
@prompt.decorate(selected_names, @color)
@prompt.decorate(selected_names, @active_color)
elsif @selected.size.nonzero?
selected_names + (@first_render ? " #{instructions}" : '')
elsif @first_render
Expand All @@ -89,7 +89,7 @@ def render_menu
indicator = (index + 1 == @active) ? @marker : Symbols::SPACE
indicator += Symbols::SPACE
message = if @selected.include?(choice)
selected = @prompt.decorate(Symbols::RADIO_CHECKED, @color)
selected = @prompt.decorate(Symbols::RADIO_CHECKED, @active_color)
selected + Symbols::SPACE + num + choice.name
else
Symbols::RADIO_UNCHECKED + Symbols::SPACE + num + choice.name
Expand Down
12 changes: 6 additions & 6 deletions lib/tty/prompt/question.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,14 @@ class Question

attr_reader :modifier

attr_reader :prompt

attr_reader :validation

# Initialize a Question
#
# @api public
def initialize(prompt, options = {})
@prompt = prompt
@prefix = options.fetch(:prefix) { @prompt.prefix }
@default = options.fetch(:default) { UndefinedSetting }
@required = options.fetch(:required) { false }
@echo = options.fetch(:echo) { true }
Expand All @@ -41,7 +40,8 @@ def initialize(prompt, options = {})
@validation = options.fetch(:validation) { UndefinedSetting }
@read = options.fetch(:read) { UndefinedSetting }
@convert = options.fetch(:convert) { UndefinedSetting }
@color = options.fetch(:color) { :green }
@active_color = options.fetch(:active_color) { @prompt.active_color }
@help_color = options.fetch(:help_color) { @prompt.help_color }
@messages = Utils.deep_copy(options.fetch(:messages) { { } })
@done = false
@input = nil
Expand Down Expand Up @@ -115,13 +115,13 @@ def render
#
# @api private
def render_question
header = "#{prompt.prefix}#{message} "
header = "#{@prefix}#{message} "
if !echo?
header
elsif @done
header += @prompt.decorate("#{@input}", @color)
header += @prompt.decorate("#{@input}", @active_color)
elsif default? && !Utils.blank?(@default)
header += @prompt.decorate("(#{default})", :bright_black) + ' '
header += @prompt.decorate("(#{default})", @help_color) + ' '
end
@prompt.print(header)
@prompt.print("\n") if @done
Expand Down
16 changes: 9 additions & 7 deletions lib/tty/prompt/slider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ class Slider
# @api public
def initialize(prompt, options = {})
@prompt = prompt
@first_render = true
@done = false
@color = options.fetch(:color) { :green }
@prefix = options.fetch(:prefix) { @prompt.prefix }
@min = options.fetch(:min) { 0 }
@max = options.fetch(:max) { 10 }
@step = options.fetch(:step) { 1 }
@default = options[:default]
@active_color = options.fetch(:active_color) { @prompt.active_color }
@help_color = options.fetch(:help_color) { @prompt.help_color }
@first_render = true
@done = false

@prompt.subscribe(self)
end
Expand Down Expand Up @@ -133,7 +135,7 @@ def render_answer
#
# @api private
def render_question
header = "#{@prompt.prefix}#{@question} #{render_header}"
header = "#{@prefix}#{@question} #{render_header}"
@prompt.puts(header)
@first_render = false
@prompt.print(render_slider) unless @done
Expand All @@ -144,9 +146,9 @@ def render_question
# @api private
def render_header
if @done
@prompt.decorate(render_answer.to_s, @color)
@prompt.decorate(render_answer.to_s, @active_color)
elsif @first_render
@prompt.decorate(HELP, :bright_black)
@prompt.decorate(HELP, @help_color)
end
end

Expand All @@ -159,7 +161,7 @@ def render_slider
output = ''
output << Symbols::SLIDER_END
output << '-' * @active
output << @prompt.decorate(Symbols::SLIDER_HANDLE, @color)
output << @prompt.decorate(Symbols::SLIDER_HANDLE, @active_color)
output << '-' * (range.size - @active - 1)
output << Symbols::SLIDER_END
output << " #{range[@active]}"
Expand Down
14 changes: 14 additions & 0 deletions spec/unit/ask_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@
].join)
end

it "changes question color" do
prompt.input << ''
prompt.input.rewind
options = {default: 'Piotr', help_color: :red, active_color: :cyan}
answer = prompt.ask("What is your name?", options)
expect(answer).to eq('Piotr')
expect(prompt.output.string).to eq([
"What is your name? \e[31m(Piotr)\e[0m ",
"\e[1000D\e[K\e[1A",
"\e[1000D\e[K",
"What is your name? \e[36mPiotr\e[0m\n"
].join)
end

it "permits empty default parameter" do
prompt.input << "\r"
prompt.input.rewind
Expand Down
Loading

0 comments on commit 1bd5c66

Please sign in to comment.