Module: Commander::UI

Defined in:
lib/commander/user_interaction.rb

Overview

User Interaction

Commander's user interaction module mixes in common methods which extend HighLine's functionality such as a #password method rather than calling #ask directly.

Defined Under Namespace

Modules: AskForClass Classes: ProgressBar

Class Method Summary collapse

Class Method Details

.applescript(script) ⇒ Object

Execute apple script.


123
124
125
# File 'lib/commander/user_interaction.rb', line 123

def applescript script
  `osascript -e "#{ script.gsub('"', '\"') }"`
end

.ask_editor(input = nil, editor = ENV['EDITOR'] || 'mate') ⇒ Object

Prompt editor for input. Optionally supply initial input which is written to the editor.

The editor defaults to the EDITOR environment variable when present, or 'mate' for TextMate.

Examples

ask_editor                # => prompts EDITOR with no input
ask_editor('foo')         # => prompts EDITOR with default text of 'foo'
ask_editor('foo', :mate)  # => prompts TextMate with default text of 'foo'

182
183
184
185
186
187
188
# File 'lib/commander/user_interaction.rb', line 182

def ask_editor input = nil, editor = ENV['EDITOR'] || 'mate'
  IO.popen(editor.to_s, 'w+') do |pipe|
    pipe.puts input.to_s unless input.nil?
    pipe.close_write
    pipe.read
  end
end

.choose(message, *choices) ⇒ Object

Choose from a set array of choices.


41
42
43
44
# File 'lib/commander/user_interaction.rb', line 41

def choose message, *choices
  say message
  super *choices
end

.converse(prompt, responses = {}) ⇒ Object

Converse with speech recognition.

Currently a “poorman's” DSL to utilize applescript and the MacOS speech recognition server.

Examples

case converse 'What is the best food?', :cookies => 'Cookies', :unknown => 'Nothing'
when :cookies 
  speak 'o.m.g. you are awesome!'
else
  case converse 'That is lame, shall I convince you cookies are the best?', :yes => 'Ok', :no => 'No', :maybe => 'Maybe another time'
  when :yes
    speak 'Well you see, cookies are just fantastic.'
  else
    speak 'Ok then, bye.'
  end
end

Notes

  • MacOS only


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/commander/user_interaction.rb', line 103

def converse prompt, responses = {}
  i, commands = 0, responses.map { |key, value| value.inspect }.join(',')
  statement = responses.inject '' do |statement, (key, value)|
    statement << (((i += 1) == 1 ? 
      %(if response is "#{value}" then\n):
        %(else if response is "#{value}" then\n))) <<
          %(do shell script "echo '#{key}'"\n)
  end
  applescript(%(
    tell application "SpeechRecognitionServer" 
      set response to listen for {#{commands}} with prompt "#{prompt}"
      #{statement}
      end if
    end tell
  )).strip.to_sym
end

.enable_pagingObject

Enable paging of output after called.


193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/commander/user_interaction.rb', line 193

def enable_paging
  return unless $stdout.tty?
  read, write = IO.pipe

  if Kernel.fork
    $stdin.reopen read
    read.close; write.close
    Kernel.select [$stdin]
    ENV['LESS'] = 'FSRX'
    pager = ENV['PAGER'] || 'less'
    exec pager rescue exec '/bin/sh', '-c', pager
  else
    $stdout.reopen write
    $stderr.reopen write if $stderr.tty?
    read.close; write.close
    return
  end
end

.io(input = nil, output = nil, &block) ⇒ Object

Normalize IO streams, allowing for redirection of input and/or output, for example:

$ foo              # => read from terminal I/O
$ foo in           # => read from 'in' file, output to terminal output stream
$ foo in out       # => read from 'in' file, output to 'out' file
$ foo < in > out   # => equivalent to above (essentially)

Optionally a block may be supplied, in which case IO will be reset once the block has executed.

Examples

command :foo do |c|
  c.syntax = 'foo [input] [output]'
  c.when_called do |args, options|
    # or io(args.shift, args.shift)
    io *args
    str = $stdin.gets
    puts 'input was: ' + str.inspect
  end
end

152
153
154
155
156
157
158
159
# File 'lib/commander/user_interaction.rb', line 152

def io input = nil, output = nil, &block
  $stdin = File.new(input) if input
  $stdout = File.new(output, 'r+') if output
  if block
    yield
    reset_io
  end
end

.log(action, *args) ⇒ Object

'Log' an action to the terminal. This is typically used for verbose output regarding actions performed. For example:

create  path/to/file.rb
remove  path/to/old_file.rb
remove  path/to/old_file2.rb

55
56
57
# File 'lib/commander/user_interaction.rb', line 55

def log action, *args
  say '%15s  %s' % [action, args.join(' ')]
end

.password(message = 'Password: ', mask = '*') ⇒ Object

Ask the user for a password. Specify a custom message other than 'Password: ' or override the default mask of '*'.


32
33
34
35
36
# File 'lib/commander/user_interaction.rb', line 32

def password message = 'Password: ', mask = '*'
  pass = ask(message) { |q| q.echo = mask }
  pass = password message, mask if pass.nil? || pass.empty?
  pass
end

.progress(arr, options = {}, &block) ⇒ Object

Output progress while iterating arr.

Examples

uris = %w( http://vision-media.ca http://google.com )
progress uris, :format => "Remaining: :time_remaining" do |uri|
  res = open uri
end

223
224
225
226
# File 'lib/commander/user_interaction.rb', line 223

def progress arr, options = {}, &block
  bar = ProgressBar.new arr.length, options
  arr.each { |v| bar.increment yield(v) }
end

.replace_tokens(str, hash) ⇒ Object

Substitute hash's keys with their associated values in str.


243
244
245
246
247
# File 'lib/commander/user_interaction.rb', line 243

def replace_tokens str, hash #:nodoc:
  hash.inject str do |str, (key, value)|
    str.gsub ":#{key}", value.to_s
  end
end

.reset_ioObject

Reset IO to initial constant streams.


164
165
166
# File 'lib/commander/user_interaction.rb', line 164

def reset_io
  $stdin, $stdout = STDIN, STDOUT
end

.speak(message, voice = :Alex) ⇒ Object

Speak message using voice which defaults to 'Alex', which is one of the better voices.

Examples

speak 'What is your favorite food? '
food = ask 'favorite food?: '
speak "wow, I like #{food} too. We have so much alike."

Notes

  • MacOS only


74
75
76
# File 'lib/commander/user_interaction.rb', line 74

def speak message, voice = :Alex
  Thread.new { applescript "say #{message.inspect} using #{voice.to_s.inspect}" }
end