vmc 0.4.7 → 0.5.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/lib/vmc.rb +1 -2
  2. data/lib/vmc/cli.rb +33 -31
  3. data/lib/vmc/cli/app/app.rb +2 -2
  4. data/lib/vmc/cli/app/apps.rb +4 -5
  5. data/lib/vmc/cli/app/crashes.rb +2 -3
  6. data/lib/vmc/cli/app/delete.rb +28 -25
  7. data/lib/vmc/cli/app/env.rb +11 -19
  8. data/lib/vmc/cli/app/files.rb +11 -15
  9. data/lib/vmc/cli/app/health.rb +2 -3
  10. data/lib/vmc/cli/app/instances.rb +3 -3
  11. data/lib/vmc/cli/app/logs.rb +7 -10
  12. data/lib/vmc/cli/app/push.rb +17 -89
  13. data/lib/vmc/cli/app/push/create.rb +2 -0
  14. data/lib/vmc/cli/app/rename.rb +17 -13
  15. data/lib/vmc/cli/app/restart.rb +4 -7
  16. data/lib/vmc/cli/app/routes.rb +14 -11
  17. data/lib/vmc/cli/app/scale.rb +17 -15
  18. data/lib/vmc/cli/app/start.rb +4 -7
  19. data/lib/vmc/cli/app/stats.rb +2 -3
  20. data/lib/vmc/cli/app/stop.rb +3 -5
  21. data/lib/vmc/cli/domain/add_domain.rb +3 -5
  22. data/lib/vmc/cli/domain/create_domain.rb +5 -8
  23. data/lib/vmc/cli/domain/delete_domain.rb +23 -18
  24. data/lib/vmc/cli/domain/domains.rb +4 -7
  25. data/lib/vmc/cli/domain/remove_domain.rb +12 -10
  26. data/lib/vmc/cli/organization/org.rb +6 -7
  27. data/lib/vmc/cli/organization/orgs.rb +19 -19
  28. data/lib/vmc/cli/organization/rename.rb +18 -14
  29. data/lib/vmc/cli/route/create_route.rb +20 -13
  30. data/lib/vmc/cli/route/{delete_route.rb → delete.rb} +22 -17
  31. data/lib/vmc/cli/service/bind.rb +2 -2
  32. data/lib/vmc/cli/service/create.rb +57 -53
  33. data/lib/vmc/cli/service/delete.rb +33 -31
  34. data/lib/vmc/cli/service/rename.rb +17 -14
  35. data/lib/vmc/cli/service/service.rb +5 -8
  36. data/lib/vmc/cli/service/services.rb +14 -18
  37. data/lib/vmc/cli/service/unbind.rb +4 -4
  38. data/lib/vmc/cli/space/create.rb +16 -17
  39. data/lib/vmc/cli/space/delete.rb +34 -31
  40. data/lib/vmc/cli/space/rename.rb +20 -17
  41. data/lib/vmc/cli/space/space.rb +11 -14
  42. data/lib/vmc/cli/space/spaces.rb +14 -16
  43. data/lib/vmc/cli/space/take.rb +1 -3
  44. data/lib/vmc/cli/start/base.rb +2 -0
  45. data/lib/vmc/cli/start/colors.rb +0 -1
  46. data/lib/vmc/cli/start/info.rb +8 -10
  47. data/lib/vmc/cli/start/login.rb +11 -40
  48. data/lib/vmc/cli/start/logout.rb +0 -1
  49. data/lib/vmc/cli/start/register.rb +18 -12
  50. data/lib/vmc/cli/start/target.rb +7 -36
  51. data/lib/vmc/cli/start/target_interactions.rb +3 -1
  52. data/lib/vmc/cli/start/targets.rb +0 -1
  53. data/lib/vmc/cli/user/create.rb +4 -2
  54. data/lib/vmc/version.rb +1 -1
  55. data/spec/factories/organization_factory.rb +5 -0
  56. data/spec/factories/space_factory.rb +15 -0
  57. data/spec/spec_helper.rb +16 -0
  58. data/spec/vmc/cli/app/push/create_spec.rb +2 -1
  59. data/spec/vmc/cli/app/push_spec.rb +1 -1
  60. data/spec/vmc/cli/organization/orgs_spec.rb +119 -0
  61. data/spec/vmc/cli/route/delete_route_spec.rb +3 -3
  62. data/spec/vmc/cli/service/bind_spec.rb +34 -0
  63. data/spec/vmc/cli/service/delete_spec.rb +32 -0
  64. data/spec/vmc/cli/service/service_spec.rb +32 -0
  65. data/spec/vmc/cli/service/unbind_spec.rb +34 -0
  66. data/spec/vmc/cli/space/spaces_spec.rb +120 -0
  67. data/spec/vmc/cli/start/info_spec.rb +38 -0
  68. data/spec/vmc/cli/start/login_spec.rb +40 -0
  69. metadata +127 -113
  70. data/lib/vmc/cli/organization/create_org.rb +0 -28
  71. data/lib/vmc/cli/organization/delete_org.rb +0 -65
  72. data/lib/vmc/cli/service/binding.rb +0 -66
  73. data/lib/vmc/cli/user.rb +0 -118
data/lib/vmc.rb CHANGED
@@ -1,9 +1,8 @@
1
1
  require "vmc/version"
2
2
 
3
3
  require "vmc/cli"
4
- require "vmc/cli/user"
5
4
 
6
- command_files = "../vmc/cli/{app,route,domain,organization,space,service,start}/*.rb"
5
+ command_files = "../vmc/cli/{app,route,domain,organization,space,service,start,user}/*.rb"
7
6
  Dir[File.expand_path(command_files, __FILE__)].each do |file|
8
7
  require file unless File.basename(file) == 'base.rb'
9
8
  end
data/lib/vmc/cli.rb CHANGED
@@ -23,36 +23,32 @@ module VMC
23
23
  include VMC::Interactive
24
24
  include VMC::Spacing
25
25
 
26
- option :help, :alias => "-h", :type => :boolean,
27
- :desc => "Show command usage & instructions"
26
+ option :help, :desc => "Show command usage", :alias => "-h",
27
+ :default => false
28
28
 
29
- option :proxy, :alias => "-u", :value => :email,
30
- :desc => "Act as another user (admin only)"
29
+ option :proxy, :desc => "Act as another user (admin)", :alias => "-u",
30
+ :value => :email
31
31
 
32
- option :version, :alias => "-v", :type => :boolean,
33
- :desc => "Print version number"
32
+ option :version, :desc => "Print version number", :alias => "-v",
33
+ :default => false
34
34
 
35
- option :verbose, :alias => "-V", :type => :boolean,
36
- :desc => "Print extra information"
35
+ option :verbose, :desc => "Print extra information", :alias => "-V",
36
+ :default => false
37
37
 
38
- option :force, :alias => "-f", :type => :boolean,
39
- :default => proc { input[:script] },
40
- :desc => "Skip interaction when possible"
38
+ option :force, :desc => "Skip interaction when possible", :alias => "-f",
39
+ :type => :boolean, :default => proc { input[:script] }
41
40
 
42
- option :quiet, :alias => "-q", :type => :boolean,
43
- :default => proc { input[:script] },
44
- :desc => "Simplify output format"
41
+ option :quiet, :desc => "Simplify output format", :alias => "-q",
42
+ :type => :boolean, :default => proc { input[:script] }
45
43
 
46
- option :script, :type => :boolean,
47
- :default => proc { !$stdout.tty? },
48
- :desc => "Shortcut for --quiet and --force"
44
+ option :script, :desc => "Shortcut for --quiet and --force",
45
+ :type => :boolean, :default => proc { !$stdout.tty? }
49
46
 
50
- option :color, :type => :boolean,
51
- :default => proc { !input[:quiet] },
52
- :desc => "Use colorful output"
47
+ option :color, :desc => "Use colorful output",
48
+ :type => :boolean, :default => proc { !input[:quiet] }
53
49
 
54
- option :trace, :alias => "-t", :type => :boolean,
55
- :desc => "Show API requests and responses"
50
+ option :trace, :desc => "Show API traffic", :alias => "-t",
51
+ :default => false
56
52
 
57
53
 
58
54
  def default_action
@@ -394,24 +390,30 @@ module VMC
394
390
 
395
391
  private
396
392
 
397
- def find_by_name(what)
398
- proc { |name, choices, *_|
393
+ def find_by_name(display, &blk)
394
+ proc { |name, *args|
395
+ choices, _ = args
396
+ choices ||= instance_exec(&blk) if block_given?
397
+
399
398
  choices.find { |c| c.name == name } ||
400
- fail("Unknown #{what} '#{name}'.")
399
+ fail("Unknown #{display} '#{name}'.")
401
400
  }
402
401
  end
403
402
 
404
- def by_name(what, obj = what)
403
+ def by_name(what, display = what)
405
404
  proc { |name, *_|
406
- client.send(:"#{obj}_by_name", name) ||
407
- fail("Unknown #{what} '#{name}'.")
405
+ client.send(:"#{what}_by_name", name) ||
406
+ fail("Unknown #{display} '#{name}'.")
408
407
  }
409
408
  end
410
409
 
411
- def find_by_name_insensitive(what)
412
- proc { |name, choices|
410
+ def find_by_name_insensitive(display, &blk)
411
+ proc { |name, *args|
412
+ choices, _ = args
413
+ choices ||= instance_exec(&blk) if block_given?
414
+
413
415
  choices.find { |c| c.name.upcase == name.upcase } ||
414
- fail("Unknown #{what} '#{name}'.")
416
+ fail("Unknown #{display} '#{name}'.")
415
417
  }
416
418
  end
417
419
  end
@@ -6,8 +6,8 @@ module VMC::App
6
6
 
7
7
  desc "Show app information"
8
8
  group :apps
9
- input :app, :argument => :required, :from_given => by_name("app"),
10
- :desc => "App to show"
9
+ input :app, :desc => "App to show", :argument => :required,
10
+ :from_given => by_name(:app)
11
11
  def app
12
12
  app = input[:app]
13
13
 
@@ -4,15 +4,14 @@ module VMC::App
4
4
  class Apps < Base
5
5
  desc "List your applications"
6
6
  group :apps
7
- input :space, :from_given => by_name("space"),
8
- :default => proc { client.current_space },
9
- :desc => "Show apps in given space"
7
+ input :space, :desc => "Show apps in given space",
8
+ :default => proc { client.current_space },
9
+ :from_given => by_name(:space)
10
10
  input :name, :desc => "Filter by name regexp"
11
11
  input :runtime, :desc => "Filter by runtime regexp"
12
12
  input :framework, :desc => "Filter by framework regexp"
13
13
  input :url, :desc => "Filter by url regexp"
14
- input :full, :type => :boolean, :default => false,
15
- :desc => "Verbose output format"
14
+ input :full, :desc => "Verbose output format", :default => false
16
15
  def apps
17
16
  if space = input[:space]
18
17
  begin
@@ -4,9 +4,8 @@ module VMC::App
4
4
  class Crashes < Base
5
5
  desc "List an app's crashed instances"
6
6
  group :apps, :info, :hidden => true
7
- input :apps, :argument => :splat, :singular => :app,
8
- :desc => "Applications whose crashed instances to list",
9
- :from_given => by_name("app")
7
+ input :apps, :desc => "Applications whose crashed instances to list",
8
+ :argument => :splat, :singular => :app, :from_given => by_name(:app)
10
9
  def crashes
11
10
  apps = input[:apps]
12
11
  fail "No applications given." if apps.empty?
@@ -6,25 +6,14 @@ module VMC::App
6
6
  class Delete < Base
7
7
  desc "Delete an application"
8
8
  group :apps, :manage
9
- input(:apps, :argument => :splat, :singular => :app,
10
- :desc => "Applications to delete",
11
- :from_given => by_name("app")) {
12
- apps = client.apps
13
- fail "No applications." if apps.empty?
14
-
15
- [ask("Delete which application?", :choices => apps.sort_by(&:name),
16
- :display => proc(&:name))]
17
- }
18
- input(:really, :type => :boolean, :forget => true,
19
- :default => proc { force? || interact }) { |name, color|
20
- ask("Really delete #{c(name, color)}?", :default => false)
21
- }
22
- input :routes, :type => :boolean, :default => false,
23
- :desc => "Delete associated routes"
24
- input :orphaned, :aliases => "-o", :type => :boolean,
25
- :desc => "Delete orphaned instances"
26
- input :all, :type => :boolean, :default => false,
27
- :desc => "Delete all applications"
9
+ input :apps, :desc => "Applications to delete", :argument => :splat,
10
+ :singular => :app, :from_given => by_name(:app)
11
+ input :routes, :desc => "Delete associated routes", :default => false
12
+ input :orphaned, :desc => "Delete orphaned services", :aliases => "-o",
13
+ :default => false
14
+ input :all, :desc => "Delete all applications", :default => false
15
+ input :really, :type => :boolean, :forget => true, :hidden => true,
16
+ :default => proc { force? || interact }
28
17
  def delete
29
18
  apps = client.apps
30
19
 
@@ -72,19 +61,33 @@ module VMC::App
72
61
  orphaned.each(&:invalidate!)
73
62
  end
74
63
 
75
- def delete_orphaned_services(instances, orphaned)
76
- return if instances.empty?
64
+ def delete_orphaned_services(service, orphaned)
65
+ return if service.empty?
77
66
 
78
67
  line unless quiet? || force?
79
68
 
80
- instances.select { |i|
69
+ service.select { |i|
81
70
  orphaned ||
82
- ask("Delete orphaned service instance #{c(i.name, :name)}?",
71
+ ask("Delete orphaned service #{c(i.name, :name)}?",
83
72
  :default => false)
84
- }.each do |instance|
73
+ }.each do |service|
85
74
  # TODO: splat
86
- invoke :delete_service, :instance => instance, :really => true
75
+ invoke :delete_service, :service => service, :really => true
87
76
  end
88
77
  end
78
+
79
+ private
80
+
81
+ def ask_app
82
+ apps = client.apps
83
+ fail "No applications." if apps.empty?
84
+
85
+ [ask("Delete which application?", :choices => apps.sort_by(&:name),
86
+ :display => proc(&:name))]
87
+ end
88
+
89
+ def ask_really(name, color)
90
+ ask("Really delete #{c(name, color)}?", :default => false)
91
+ end
89
92
  end
90
93
  end
@@ -6,9 +6,8 @@ module VMC::App
6
6
 
7
7
  desc "Show all environment variables set for an app"
8
8
  group :apps, :info, :hidden => true
9
- input :app, :argument => true,
10
- :desc => "Application to inspect the environment of",
11
- :from_given => by_name("app")
9
+ input :app, :desc => "Application to inspect the environment of",
10
+ :argument => true, :from_given => by_name(:app)
12
11
  def env
13
12
  app = input[:app]
14
13
 
@@ -26,15 +25,11 @@ module VMC::App
26
25
 
27
26
  desc "Set an environment variable"
28
27
  group :apps, :info, :hidden => true
29
- input :app, :argument => true,
30
- :desc => "Application to set the variable for",
31
- :from_given => by_name("app")
32
- input :name, :argument => true,
33
- :desc => "Environment variable name"
34
- input :value, :argument => :optional,
35
- :desc => "Environment variable value"
36
- input :restart, :type => :boolean, :default => true,
37
- :desc => "Restart app after updating?"
28
+ input :app, :desc => "Application to set the variable for",
29
+ :argument => true, :from_given => by_name(:app)
30
+ input :name, :desc => "Variable name", :argument => true
31
+ input :value, :desc => "Variable value", :argument => :optional
32
+ input :restart, :desc => "Restart app after updating?", :default => true
38
33
  def set_env
39
34
  app = input[:app]
40
35
  name = input[:name]
@@ -62,13 +57,10 @@ module VMC::App
62
57
 
63
58
  desc "Remove an environment variable"
64
59
  group :apps, :info, :hidden => true
65
- input :app, :argument => true,
66
- :desc => "Application to set the variable for",
67
- :from_given => by_name("app")
68
- input :name, :argument => true,
69
- :desc => "Environment variable name"
70
- input :restart, :type => :boolean, :default => true,
71
- :desc => "Restart app after updating?"
60
+ input :app, :desc => "Application to set the variable for",
61
+ :argument => true, :from_given => by_name(:app)
62
+ input :name, :desc => "Variable name", :argument => true
63
+ input :restart, :desc => "Restart app after updating?", :default => true
72
64
  def unset_env
73
65
  app = input[:app]
74
66
  name = input[:name]
@@ -5,11 +5,10 @@ module VMC::App
5
5
  class Files < Base
6
6
  desc "Print out an app's file contents"
7
7
  group :apps, :info, :hidden => true
8
- input :app, :argument => true,
9
- :desc => "Application to inspect the files of",
10
- :from_given => by_name("app")
11
- input :path, :argument => true, :default => "/",
12
- :desc => "Path of file to read"
8
+ input :app, :desc => "Application to inspect the files of",
9
+ :argument => true, :from_given => by_name(:app)
10
+ input :path, :desc => "Path of file to read", :argument => :optional,
11
+ :default => "/"
13
12
  def file
14
13
  app = input[:app]
15
14
  path = input[:path]
@@ -36,11 +35,10 @@ module VMC::App
36
35
 
37
36
  desc "Examine an app's files"
38
37
  group :apps, :info, :hidden => true
39
- input :app, :argument => true,
40
- :desc => "Application to inspect the files of",
41
- :from_given => by_name("app")
42
- input :path, :argument => :optional, :default => "/",
43
- :desc => "Path of directory to list"
38
+ input :app, :desc => "Application to inspect the files of",
39
+ :argument => true, :from_given => by_name(:app)
40
+ input :path, :desc => "Path of directory to list", :argument => :optional,
41
+ :default => "/"
44
42
  def files
45
43
  app = input[:app]
46
44
  path = input[:path]
@@ -65,11 +63,9 @@ module VMC::App
65
63
 
66
64
  desc "Stream an app's file contents"
67
65
  group :apps, :info, :hidden => true
68
- input :app, :argument => true,
69
- :desc => "Application to inspect the file of",
70
- :from_given => by_name("app")
71
- input :path, :argument => :optional, :default => nil,
72
- :desc => "Path of file to stream (default: all)"
66
+ input :app, :desc => "Application to inspect the files of",
67
+ :argument => true, :from_given => by_name(:app)
68
+ input :path, :desc => "Path of file to stream", :argument => :optional
73
69
  def tail
74
70
  app = input[:app]
75
71
 
@@ -4,9 +4,8 @@ module VMC::App
4
4
  class Health < Base
5
5
  desc "Get application health"
6
6
  group :apps, :info, :hidden => true
7
- input :apps, :argument => :splat, :singular => :app,
8
- :desc => "Applications to start",
9
- :from_given => by_name("app")
7
+ input :apps, :desc => "Applications to start", :argument => :splat,
8
+ :singular => :app, :from_given => by_name(:app)
10
9
  def health
11
10
  apps = input[:apps]
12
11
  fail "No applications given." if apps.empty?
@@ -4,9 +4,9 @@ module VMC::App
4
4
  class Instances < Base
5
5
  desc "List an app's instances"
6
6
  group :apps, :info, :hidden => true
7
- input :apps, :argument => :splat, :singular => :app,
8
- :desc => "Applications whose instances to list",
9
- :from_given => by_name("app")
7
+ input :apps, :desc => "Applications whose instances to list",
8
+ :argument => :splat, :singular => :app,
9
+ :from_given => by_name(:app)
10
10
  def instances
11
11
  apps = input[:apps]
12
12
  fail "No applications given." if apps.empty?
@@ -4,13 +4,11 @@ module VMC::App
4
4
  class Logs < Base
5
5
  desc "Print out an app's logs"
6
6
  group :apps, :info, :hidden => true
7
- input :app, :argument => true,
8
- :desc => "Application to get the logs of",
9
- :from_given => by_name("app")
10
- input :instance, :default => "0",
11
- :desc => "Instance of application to get the logs of"
12
- input :all, :type => :boolean, :default => false,
13
- :desc => "Get logs for every instance"
7
+ input :app, :desc => "Application to get the logs of", :argument => true,
8
+ :from_given => by_name(:app)
9
+ input :instance, :desc => "Instance of application to get the logs of",
10
+ :default => "0"
11
+ input :all, :desc => "Get logs for every instance", :default => false
14
12
  def logs
15
13
  app = input[:app]
16
14
 
@@ -36,9 +34,8 @@ module VMC::App
36
34
 
37
35
  desc "Print out the logs for an app's crashed instances"
38
36
  group :apps, :info, :hidden => true
39
- input :app, :argument => true,
40
- :desc => "Application to get the logs of",
41
- :from_given => by_name("app")
37
+ input :app, :desc => "Application to get the logs of", :argument => true,
38
+ :from_given => by_name(:app)
42
39
  def crashlogs
43
40
  app = input[:app]
44
41
 
@@ -1,7 +1,7 @@
1
- require "vmc/detect"
2
1
  require "vmc/cli/app/base"
3
2
  require "vmc/cli/app/push/sync"
4
3
  require "vmc/cli/app/push/create"
4
+ require "vmc/cli/app/push/interactions"
5
5
 
6
6
  module VMC::App
7
7
  class Push < Base
@@ -10,67 +10,22 @@ module VMC::App
10
10
 
11
11
  desc "Push an application, syncing changes if it exists"
12
12
  group :apps, :manage
13
- input(:name, :argument => true, :desc => "Application name") {
14
- ask("Name")
15
- }
16
- input :path, :default => ".",
17
- :desc => "Path containing the application"
18
- input(:url, :desc => "URL bound to app") { |name|
19
- choices = url_choices(name)
20
-
21
- options = {
22
- :choices => choices + ["none"],
23
- :allow_other => true
24
- }
25
-
26
- options[:default] = choices.first if choices.size == 1
27
-
28
- url = ask "URL", options
29
-
30
- unless url == "none"
31
- url
32
- end
33
- }
34
- input(:memory, :desc => "Memory limit") { |default|
35
- ask("Memory Limit",
36
- :choices => memory_choices,
37
- :allow_other => true,
38
- :default => default || "64M")
39
- }
40
- input(:instances, :type => :integer,
41
- :desc => "Number of instances to run") {
42
- ask("Instances", :default => 1)
43
- }
44
- input(:framework, :from_given => by_name("framework"),
45
- :desc => "Framework to use") { |choices, default, other|
46
- ask_with_other("Framework", client.frameworks, choices, default, other)
47
- }
48
- input(:runtime, :from_given => by_name("runtime"),
49
- :desc => "Runtime to use") { |choices, default, other|
50
- ask_with_other("Runtime", client.runtimes, choices, default, other)
51
- }
52
- input(:command, :desc => "Startup command for standalone app") {
53
- ask("Startup command")
54
- }
55
- input :plan, :default => "D100",
56
- :desc => "Application plan (e.g. D100, P200)"
57
- input :start, :type => :boolean, :default => true,
58
- :desc => "Start app after pushing?"
59
- input :restart, :type => :boolean, :default => true,
60
- :desc => "Restart app after updating?"
61
- input(:create_services, :type => :boolean,
62
- :default => proc { force? ? false : interact },
63
- :desc => "Interactively create services?") {
64
- line unless quiet?
65
- ask "Create services for application?", :default => false
66
- }
67
- input(:bind_services, :type => :boolean,
68
- :default => proc { force? ? false : interact },
69
- :desc => "Interactively bind services?") {
70
- unless all_instances.empty?
71
- ask "Bind other services to application?", :default => false
72
- end
73
- }
13
+ input :name, :desc => "Application name", :argument => :optional
14
+ input :path, :desc => "Path containing the bits", :default => "."
15
+ input :url, :desc => "URL to bind to app"
16
+ input :memory, :desc => "Memory limit"
17
+ input :instances, :desc => "Number of instances to run"
18
+ input :framework, :desc => "Framework to use", :from_given => by_name(:framework)
19
+ input :runtime, :desc => "Runtime to use", :from_given => by_name(:runtime)
20
+ input :command, :desc => "Startup command for standalone app"
21
+ input :plan, :desc => "Application plan", :default => "D100"
22
+ input :start, :desc => "Start app after pushing?", :default => true
23
+ input :restart, :desc => "Restart app after updating?", :default => true
24
+ input :create_services, :desc => "Interactively create services?",
25
+ :type => :boolean, :default => proc { force? ? false : interact }
26
+ input :bind_services, :desc => "Interactively bind services?",
27
+ :type => :boolean, :default => proc { force? ? false : interact }
28
+ interactions PushInteractions
74
29
  def push
75
30
  name = input[:name]
76
31
  path = File.expand_path(input[:path])
@@ -122,32 +77,5 @@ module VMC::App
122
77
  err "Upload failed. Try again with 'vmc push'."
123
78
  raise
124
79
  end
125
-
126
- def ask_with_other(message, all, choices, default, other)
127
- choices = choices.sort_by(&:name)
128
- choices << other if other
129
-
130
- opts = {
131
- :choices => choices,
132
- :display => proc { |x|
133
- if other && x == other
134
- "other"
135
- else
136
- x.name
137
- end
138
- }
139
- }
140
-
141
- opts[:default] = default if default
142
-
143
- res = ask(message, opts)
144
-
145
- if other && res == other
146
- opts[:choices] = all
147
- res = ask(message, opts)
148
- end
149
-
150
- res
151
- end
152
80
  end
153
81
  end