epubforge 0.0.10 → 0.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +17 -10
  3. data/VERSION +1 -1
  4. data/bin/epubforge +1 -1
  5. data/config/actions/epub.rb +50 -0
  6. data/config/actions/forge.rb +34 -13
  7. data/config/actions/git.rb +106 -0
  8. data/config/actions/help.rb +13 -13
  9. data/config/actions/html.rb +33 -0
  10. data/config/actions/mobi.rb +60 -0
  11. data/config/actions/new.rb +182 -0
  12. data/config/actions/word_count.rb +26 -24
  13. data/config/{actions → actions_to_ignore}/generate.rb +1 -1
  14. data/config/{actions → actions_to_ignore}/generate_chapter.rb +0 -0
  15. data/config/{actions → actions_to_ignore}/git_backup.rb +2 -2
  16. data/config/{actions → actions_to_ignore}/globals.rb +1 -1
  17. data/config/{actions → actions_to_ignore}/kindle.rb +3 -3
  18. data/config/{actions → actions_to_ignore}/local_action.rb +1 -1
  19. data/config/{actions → actions_to_ignore}/mobify.rb +3 -3
  20. data/config/actions_to_ignore/notes_to_epub.rb +19 -0
  21. data/config/actions_to_ignore/notes_to_kindle.rb +18 -0
  22. data/config/{actions → actions_to_ignore}/spell.rb +1 -1
  23. data/config/{actions → actions_to_ignore}/version.rb +3 -3
  24. data/config/{actions → actions_to_ignore}/wrap_scene_notes_in_hidden_div.rb +1 -1
  25. data/config/converters/epub_to_mobi.calibre.rb +8 -0
  26. data/config/converters/epub_to_mobi.kindlegen.rb +11 -0
  27. data/config/html_translators/default_kramdown.html_translator.rb +9 -0
  28. data/config/html_translators/default_markdown.html_translator.rb +10 -0
  29. data/config/html_translators/default_markdown_pandoc.html_translator.rb +10 -0
  30. data/config/html_translators/default_textile_pandoc.html_translator.rb +8 -0
  31. data/config/html_translators/default_xhtml.html_translator.rb +7 -0
  32. data/config/html_translators/fallback_html.html_translator.rb +9 -0
  33. data/config/html_translators/fallback_markdown.html_translator.rb +8 -0
  34. data/config/html_translators/fallback_textile.html_translator.rb +7 -0
  35. data/config/html_translators/fallback_txt.html_translator.rb +8 -0
  36. data/config/html_translators/fallback_unknown.html_translator.rb +7 -0
  37. data/lib/epubforge.rb +37 -82
  38. data/lib/{action/thor_action.rb → epubforge/action/action.rb} +89 -69
  39. data/lib/epubforge/action/action2.rb +109 -0
  40. data/lib/epubforge/action/action_definition.rb +62 -0
  41. data/lib/epubforge/action/actions_lookup.rb +45 -0
  42. data/lib/epubforge/action/chatterbox.rb +93 -0
  43. data/lib/{action → epubforge/action}/cli_command.rb +2 -2
  44. data/lib/{action → epubforge/action}/cli_sequence.rb +0 -0
  45. data/lib/{action → epubforge/action}/file_transformer.rb +0 -0
  46. data/lib/{action → epubforge/action}/hooks_interface.rb +2 -2
  47. data/lib/{action → epubforge/action}/run_description.rb +12 -9
  48. data/lib/{action → epubforge/action}/runner.rb +23 -24
  49. data/lib/{epub → epubforge/builder}/assets/asset.rb +1 -1
  50. data/lib/{epub → epubforge/builder}/assets/font.rb +1 -1
  51. data/lib/epubforge/builder/assets/html.rb +9 -0
  52. data/lib/{epub → epubforge/builder}/assets/image.rb +1 -1
  53. data/lib/epubforge/builder/assets/markdown.rb +9 -0
  54. data/lib/{epub → epubforge/builder}/assets/page.rb +12 -4
  55. data/lib/{epub → epubforge/builder}/assets/stylesheet.rb +1 -1
  56. data/lib/epubforge/builder/assets/textile.rb +9 -0
  57. data/lib/epubforge/builder/assets/xhtml.rb +9 -0
  58. data/lib/epubforge/builder/builder.rb +134 -0
  59. data/lib/{epub/builder.rb → epubforge/builder/epub.rb} +58 -161
  60. data/lib/epubforge/builder/html.rb +22 -0
  61. data/lib/epubforge/builder/packager.rb +16 -0
  62. data/lib/epubforge/core_extensions/array.rb +2 -0
  63. data/lib/{core_extensions → epubforge/core_extensions}/kernel.rb +0 -0
  64. data/lib/epubforge/core_extensions/nil_class.rb +2 -0
  65. data/lib/epubforge/core_extensions/object.rb +24 -0
  66. data/lib/{core_extensions → epubforge/core_extensions}/string.rb +1 -5
  67. data/lib/{custom_helpers.rb → epubforge/custom_helpers.rb} +0 -1
  68. data/lib/{errors.rb → epubforge/exceptions/errors.rb} +0 -0
  69. data/lib/{project → epubforge/project}/project.rb +23 -17
  70. data/lib/epubforge/utils/action_loader.rb +8 -0
  71. data/lib/epubforge/utils/class_loader.rb +102 -0
  72. data/lib/epubforge/utils/converter.rb +94 -0
  73. data/lib/{utils → epubforge/utils}/downloader.rb +0 -0
  74. data/lib/{utils → epubforge/utils}/file_orderer.rb +0 -0
  75. data/lib/epubforge/utils/file_path.rb +8 -0
  76. data/lib/epubforge/utils/html_translator.rb +126 -0
  77. data/lib/epubforge/utils/html_translator_queue.rb +113 -0
  78. data/lib/epubforge/utils/htmlizer.rb +61 -0
  79. data/lib/{utils → epubforge/utils}/misc.rb +0 -0
  80. data/lib/epubforge/utils/root_path.rb +8 -0
  81. data/lib/epubforge/utils/settings.rb +147 -0
  82. data/lib/epubforge/utils/template_evaluator.rb +7 -0
  83. data/templates/{default/book/afterword.markdown.template → project/book/afterword.markdown} +0 -0
  84. data/templates/project/book/chapter-%0000chapter%.markdown.template +4 -0
  85. data/templates/{default → project}/book/cover.xhtml.template +2 -2
  86. data/templates/{default/book/foreword.markdown.template → project/book/foreword.markdown} +0 -0
  87. data/templates/{default → project}/book/images/cover.png +0 -0
  88. data/templates/{default/book/stylesheets/stylesheet.css.template → project/book/stylesheets/stylesheet.css} +0 -0
  89. data/templates/project/book/title_page.markdown.template +5 -0
  90. data/templates/project/notes/character.%character.name_for_file%.markdown.template +15 -0
  91. data/templates/{default → project}/notes/images/cover.png +0 -0
  92. data/templates/{default/notes/stylesheets/stylesheet.css.template → project/notes/stylesheets/stylesheet.css} +0 -0
  93. data/templates/{default → project}/settings/actions/local_action.rb.example +1 -1
  94. data/templates/project/settings/config.rb.template +70 -0
  95. data/templates/project/settings/html_translators/example_translator.rb +29 -0
  96. data/templates/{default → project}/settings/wordcount.template +1 -1
  97. data/test/answers01.yml +30 -0
  98. data/test/helper.rb +62 -39
  99. data/test/misc/config.rb +5 -7
  100. data/test/test_epubforge.rb +18 -14
  101. data/test/{test_htmlizers.rb → test_html_translators.rb} +4 -8
  102. data/test/test_template_evaluator.rb +42 -0
  103. data/test/test_utils.rb +0 -11
  104. metadata +186 -189
  105. data/config/actions/gitify.rb +0 -72
  106. data/config/actions/init.rb +0 -138
  107. data/config/actions/notes_to_epub.rb +0 -18
  108. data/config/actions/notes_to_kindle.rb +0 -17
  109. data/config/htmlizers.rb +0 -70
  110. data/lib/action/actions_lookup.rb +0 -45
  111. data/lib/core_extensions/array.rb +0 -5
  112. data/lib/core_extensions/nil_class.rb +0 -5
  113. data/lib/core_extensions/object.rb +0 -5
  114. data/lib/epub/assets/html.rb +0 -8
  115. data/lib/epub/assets/markdown.rb +0 -8
  116. data/lib/epub/assets/textile.rb +0 -8
  117. data/lib/epub/assets/xhtml.rb +0 -8
  118. data/lib/epub/packager.rb +0 -16
  119. data/lib/utils/action_loader.rb +0 -7
  120. data/lib/utils/class_loader.rb +0 -102
  121. data/lib/utils/directory_builder.rb +0 -181
  122. data/lib/utils/file_path.rb +0 -152
  123. data/lib/utils/html_translator.rb +0 -100
  124. data/lib/utils/html_translator_queue.rb +0 -70
  125. data/lib/utils/htmlizer.rb +0 -92
  126. data/lib/utils/root_path.rb +0 -20
  127. data/lib/utils/settings.rb +0 -146
  128. data/lib/utils/template_evaluator.rb +0 -20
  129. data/templates/default/book/chapter-%i%.markdown.sequence +0 -4
  130. data/templates/default/book/title_page.markdown.template +0 -4
  131. data/templates/default/notes/character.named.markdown.template +0 -4
  132. data/templates/default/payload.rb +0 -65
  133. data/templates/default/settings/config.rb.form +0 -55
  134. data/templates/default/settings/htmlizers.rb +0 -0
  135. data/test/test_directory_builder.rb +0 -141
@@ -1,65 +1,80 @@
1
1
  module EpubForge
2
2
  module Action
3
3
  module SharedActionInterface
4
- def actions_lookup
5
- if self == ThorAction
6
- @actions_lookup ||= ActionsLookup.new
7
- else
8
- ThorAction.actions_lookup
9
- end
10
- end
4
+ # def actions_lookup
5
+ # if self == Action
6
+ # @actions_lookup ||= ActionsLookup.new
7
+ # else
8
+ # Action.actions_lookup
9
+ # end
10
+ # end
11
11
 
12
- def register_action_subclass( klass )
13
- if self == ThorAction
14
- @subclasses ||= []
15
- @subclasses = (@subclasses + [klass]).uniq
16
- else
17
- ThorAction.register_action_subclass( klass )
18
- end
19
- end
12
+ # def register_action_subclass( klass )
13
+ # if self == Action
14
+ # @subclasses ||= []
15
+ # @subclasses = (@subclasses + [klass]).uniq
16
+ # else
17
+ # Action.register_action_subclass( klass )
18
+ # end
19
+ # end
20
20
 
21
- def subclasses
22
- if self == ThorAction
23
- @subclasses
24
- else
25
- ThorAction.subclasses
26
- end
27
- end
21
+ # def subclasses
22
+ # if self == Action
23
+ # @subclasses
24
+ # else
25
+ # Action.subclasses
26
+ # end
27
+ # end
28
28
 
29
- def command_to_action_classes
30
- if self == ThorAction
31
- @command_klass_lookup ||= {}
32
- else
33
- ThorAction.command_to_action_classes
34
- end
35
- end
29
+ # def command_to_action_classes
30
+ # if self == Action
31
+ # @command_klass_lookup ||= {}
32
+ # else
33
+ # Action.command_to_action_classes
34
+ # end
35
+ # end
36
36
 
37
- def description( str = nil )
38
- @description = str if str
39
- @description
40
- end
37
+ get_and_set( :description )
38
+ # def description( str = nil )
39
+ # @description = str if str
40
+ # @description
41
+ # end
41
42
 
42
43
  # eventually replace description
43
44
  def desc( usage, description, options = {} )
45
+ verbose = defined?(EpubForge::Action::Character) && self == EpubForge::Action::Character
46
+ puts "--------------IN DESC()----------------" if verbose
47
+ puts self.method_options.inspect if verbose
44
48
  self.command_to_action_classes[usage] = self
45
49
  super( usage, description, options )
50
+ puts self.method_options.inspect if verbose
51
+ puts "--------------END DESC()----------------" if verbose
46
52
  end
47
53
 
48
- # TODO: Get rid of this
49
- def keywords( *args )
50
- if args.epf_blank?
51
- @keywords ||= []
52
- else
53
- @keywords = args.map(&:to_s)
54
- end
55
-
56
- @keywords
57
- end
54
+ # # TODO: Get rid of this
55
+ # def keywords( *args )
56
+ # if args.fwf_blank?
57
+ # @keywords ||= []
58
+ # else
59
+ # @keywords = args.map(&:to_s)
60
+ # end
61
+ #
62
+ # @keywords
63
+ # end
58
64
 
59
- def usage( str = nil )
60
- @usage = str if str
61
- @usage
62
- end
65
+ # If given one arg, sets keyword
66
+ # if given no args, fetches keyword
67
+ get_and_set( :keyword, :usage ) #
68
+ # def keyword( k = nil )
69
+ # @keyword = k unless k.nil?
70
+ # @keyword
71
+ # end
72
+ #
73
+ #
74
+ # def usage( str = nil )
75
+ # @usage = str if str
76
+ # @usage
77
+ # end
63
78
 
64
79
  def project_required?
65
80
  @project_required = true if @project_required.nil?
@@ -83,11 +98,11 @@ module EpubForge
83
98
  end
84
99
  end
85
100
 
86
- class ThorAction < Thor
87
- def self.inherited( subclass )
88
- self.register_action_subclass( subclass )
89
- subclass.include_standard_options
90
- end
101
+ class Action < Thor
102
+ # def self.inherited( subclass )
103
+ # self.register_action_subclass( subclass )
104
+ # subclass.include_standard_options
105
+ # end
91
106
 
92
107
  include Thor::Actions
93
108
  extend SharedActionInterface
@@ -102,6 +117,9 @@ module EpubForge
102
117
  ON_BLUE = Thor::Shell::Color::ON_BLUE
103
118
 
104
119
 
120
+
121
+
122
+
105
123
  protected
106
124
  def say_when_verbose( *args )
107
125
  say( *args ) if @verbose
@@ -142,9 +160,9 @@ module EpubForge
142
160
  end
143
161
 
144
162
  choice_text = ""
145
- choices.each_with_index{ |choice,i|
163
+ choices.each_with_index do |choice,i|
146
164
  choice_text << "\t\t#{i}) #{choice.first}\n"
147
- }
165
+ end
148
166
 
149
167
  selection = ask( "#{statement}\n\tChoices:\n#{choice_text}>>> ", BLUE )
150
168
  choices[selection.to_i].last
@@ -153,6 +171,8 @@ module EpubForge
153
171
  def ask_prettily( statement )
154
172
  ask( statement, BLUE )
155
173
  end
174
+
175
+
156
176
 
157
177
  # hope this doesn't break anything. Sure enough, it broke a lot of things.
158
178
  # def destination_root=( root )
@@ -160,16 +180,6 @@ module EpubForge
160
180
  # @destination_stack << (root ? root.fwf_filepath.expand : '')
161
181
  # end
162
182
 
163
- # Instead, use these instead of destination_root. Thor gets strings instead of
164
- # filepaths, like it wants, and I get filepaths instead of strings, like I want.
165
- def destination_root_filepath
166
- self.destination_root.fwf_filepath
167
- end
168
-
169
- def destination_root_filepath=(root)
170
- self.destination_root = root.to_s
171
- end
172
-
173
183
  def executable_installed?( name )
174
184
  name = name.to_sym
175
185
 
@@ -218,7 +228,7 @@ module EpubForge
218
228
  end
219
229
 
220
230
  def project_already_gitted?
221
- @project.target_dir.join( ".git" ).directory?
231
+ @project.root_dir.join( ".git" ).directory?
222
232
  end
223
233
 
224
234
  def quit_with_error( msg, errno = -1 )
@@ -227,12 +237,22 @@ module EpubForge
227
237
  end
228
238
 
229
239
  def before_start
230
- @project = @options[:project]
231
- @debug = @options[:debug]
232
- @help = @options[:help]
233
- @verbose = @options[:verbose]
240
+ variablize_options( :project, :debug, :help, :verbose )
241
+ # @project = @options[:project]
242
+ # @debug = @options[:debug]
243
+ # @help = @options[:help]
244
+ # @verbose = @options[:verbose]
234
245
  @project = Project.new( @project ) unless @project.nil?
235
246
  end
247
+
248
+ # takes a series of symbols or an array of symbols
249
+ # for each symbol, creates an instance var from @options[:symbol]
250
+ def variablize_options( *symbols )
251
+ symbols.flatten! # in case someone passes an array
252
+ for sym in symbols
253
+ self.instance_variable_set( :"@#{sym}", @options[sym] )
254
+ end
255
+ end
236
256
  end
237
257
  end
238
258
  end
@@ -0,0 +1,109 @@
1
+ module EpubForge
2
+ module Action
3
+ class Action2
4
+ get_and_set( :project, :args )
5
+ get_and_set_boolean( :verbose )
6
+
7
+ include FunWith::Patterns::Loader
8
+ loader_pattern_configure( :bracketwise_lookup,
9
+ :warn_on_key_change,
10
+ { :verbose => true } )
11
+
12
+
13
+
14
+ include Chatterbox
15
+
16
+ def self.loader_pattern_load_item( file )
17
+ begin
18
+ file.fwf_filepath.load
19
+ rescue Exception => e
20
+ puts "Error loading #{file}: #{e.message}"
21
+ for line in e.backtrace
22
+ puts "\t#{line}"
23
+ end
24
+ end
25
+
26
+ nil # returning true will break loader
27
+ end
28
+
29
+ def self.define_action( keyword, &block )
30
+ puts "defining action #{keyword}" if EpubForge.gem_test_mode?
31
+ definition = ActionDefinition.new
32
+ definition.keyword( keyword )
33
+ definition.klass( self )
34
+
35
+ yield definition if block_given?
36
+
37
+ EpubForge::Action::Action2.loader_pattern_register_item( definition )
38
+ end
39
+
40
+ # # Instead, use these instead of destination_root. Thor gets strings instead of
41
+ # # filepaths, like it wants, and I get filepaths instead of strings, like I want.
42
+ # def destination_root_filepath
43
+ # self.destination_root.fwf_filepath
44
+ # end
45
+ #
46
+ # def destination_root_filepath=(root)
47
+ # @destination_root_file
48
+ # self.destination_root = root.to_s
49
+ # end
50
+ attr_accessor :destination_root_filepath
51
+
52
+ def executable_installed?( name )
53
+ name = name.to_sym
54
+
55
+ if @executables.nil?
56
+ @executables = {}
57
+ for exe, path in (EpubForge.config[:exe_paths] || {})
58
+ @executables[exe] = path.fwf_filepath
59
+ end
60
+ end
61
+
62
+ @executables[name] ||= begin
63
+ _which = `which #{name}`.strip
64
+ (_which.length == 0) ? false : _which.fwf_filepath
65
+ end
66
+
67
+ @executables[name]
68
+ end
69
+
70
+ def requirements
71
+ @requirements ||= []
72
+ end
73
+
74
+ def add_requirement( *args, &block )
75
+ @requirements ||= []
76
+ @requirements.push( [args, block] )
77
+ end
78
+
79
+ def requires_executable( ex, fail_msg )
80
+ add_requirement( ex, fail_msg ) do
81
+ executable_installed?( ex, fail_msg )
82
+ end
83
+ end
84
+
85
+ def must_target_a_project( project_dir )
86
+ add_requirement( project_dir ) do
87
+ Project.is_project_dir?( project_dir )
88
+ end
89
+ end
90
+
91
+ def git_installed?
92
+ executable_installed?('git')
93
+ end
94
+
95
+ def ebook_convert_installed?
96
+ executable_installed?('ebook-convert')
97
+ end
98
+
99
+ def project_already_gitted?
100
+ @project.root_dir.join( ".git" ).directory?
101
+ end
102
+
103
+ def quit_with_error( msg, errno = -1 )
104
+ STDERR.write( "\n#{msg}\n")
105
+ exit( errno )
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,62 @@
1
+ module EpubForge
2
+ module Action
3
+ class ActionDefinition
4
+ # attr_accessor :default_args, :keyword, :klass, :proc
5
+
6
+ get_and_set :help, :usage, :default_args, :keyword, :klass, :proc
7
+ get_and_set_boolean :project_required, :verbose
8
+
9
+ alias :loader_pattern_registry_key :keyword
10
+
11
+ def execute( &block )
12
+ proc( block )
13
+ end
14
+
15
+ def run( *args )
16
+ action = klass.new # one of the action classes (New or Git or Epub, etc.)
17
+ puts( "Sending args to Action(#{self.keyword}) : #{ 'NO ARGS' if args.fwf_blank? }".paint(:pink) ) if EpubForge.gem_test_mode?
18
+ for arg, i in args.each_with_index
19
+ puts " #{i}: #{arg.inspect}".paint(:pink) if verbose?
20
+ end
21
+
22
+ if args.first.is_a?(Project)
23
+ action.project( args.first )
24
+ action.args( args[1..-1] )
25
+ else
26
+ action.args( args )
27
+ end
28
+
29
+ action.instance_exec( &@proc )
30
+ end
31
+
32
+
33
+ def default( name, value )
34
+ (@default_args ||= {})[name] = value
35
+ end
36
+
37
+ # def project_required?
38
+ # @project_required = true if @project_required.nil?
39
+ # @project_required
40
+ # end
41
+
42
+ # def verbose?
43
+ # @verbose == true
44
+ # end
45
+
46
+ # Most actions require -- nay, demand! -- a project to act upon.
47
+ # Add the line 'project_not_required' to the class definition
48
+ # to keep it from failing out if it can't find an existing project.
49
+ # Used for things like initializing new projects, printing help,
50
+ # or... my imagination fails me.
51
+ def project_required?
52
+ @project_required = true if @project_required.nil?
53
+ @project_required
54
+ end
55
+
56
+
57
+ def project_not_required
58
+ @project_required = false
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,45 @@
1
+ # module EpubForge
2
+ # module Action
3
+ # class ActionsLookup
4
+ # attr_accessor :actions, :actions_directories, :keywords
5
+ #
6
+ # def initialize
7
+ # clear
8
+ # end
9
+ #
10
+ # def clear
11
+ # @keywords = {}
12
+ # @actions = []
13
+ # @actions_directories = []
14
+ # end
15
+ #
16
+ # def add_actions( *args )
17
+ # Utils::ActionLoader.load_me( *args )
18
+ #
19
+ # new_actions = Utils::ActionLoader.loaded_classes - @actions
20
+ # @actions += new_actions
21
+ # new_directories = Utils::ActionLoader.loaded_directories - @actions_directories
22
+ # @actions_directories += new_directories
23
+ #
24
+ # for action in new_actions
25
+ # for keyword in action.keywords
26
+ # @keywords[keyword] = action
27
+ # end
28
+ # end
29
+ # end
30
+ #
31
+ # # Find all the actions with keywords that start with the given string.
32
+ # # If this results in more than one action being found, the proper
33
+ # # response is to panic and flail arms.
34
+ # def keyword_to_action( keyword )
35
+ # exact_match = @keywords.keys.select{ |k| k == keyword }
36
+ #
37
+ # return [@keywords[exact_match.first]] if exact_match.length == 1
38
+ #
39
+ # # if no exact match can be found, find a partial match, at the beginning
40
+ # # of the keywords.
41
+ # @keywords.keys.select{ |k| k.match(/^#{keyword}/) }.map{ |k| @keywords[k] }.uniq
42
+ # end
43
+ # end
44
+ # end
45
+ # end
@@ -0,0 +1,93 @@
1
+ module EpubForge
2
+ module Action
3
+ module Chatterbox
4
+ def say( message, color = nil )
5
+ puts message.paint(color)
6
+ end
7
+
8
+ def ask( question, opts = {} )
9
+ while true
10
+ opts[:colors] ||= opts[:color]
11
+
12
+ answer = nil
13
+ input = Readline.readline( question.paint(opts[:colors] ) + " " ).strip
14
+ input.strip
15
+
16
+ if input.fwf_blank?
17
+ if opts[:default]
18
+ answer = opts[:default]
19
+ elsif opts[:blank_allowed] || (opts[:possible_answers] || []).include?("")
20
+ answer = input
21
+ end
22
+ elsif opts[:possible_answers]
23
+ answer = input if opts[:possible_answers].include?( input )
24
+ else
25
+ answer = input
26
+ end
27
+
28
+ if answer.nil?
29
+ say( "'#{input}' is not a valid answer.", :red )
30
+ say( "Possible answers: #{ opts[:possible_answers].inspect }") if opts[:possible_answers]
31
+ end
32
+
33
+ return answer unless answer.nil?
34
+ end
35
+ end
36
+
37
+ def yes?( message, opts = {} )
38
+ opts[:colors] ||= :blue
39
+ opts[:possible_answers] = ["Y", "y", "N", "n", "yes", "no"]
40
+ opts[:default] ||= "y"
41
+
42
+ answer = ask( "#{message} (Y/n)", opts ).downcase[0..1]
43
+
44
+ answer == "y"
45
+ end
46
+
47
+ def yes_prettily?( statement )
48
+ yes?( statement, :color => :pink )
49
+ end
50
+
51
+
52
+ def no?( message, color = nil )
53
+ opts[:allowed] = ["Y", "y", "N", "n"]
54
+ opts[:default] = "n"
55
+ answer = ask( "#{message} (y/N)", opts ).downcase
56
+
57
+ answer == "n"
58
+ end
59
+
60
+ def say_instruction( instruction )
61
+ puts instruction.paint(:yellow)
62
+ end
63
+
64
+
65
+ def ask_from_menu( statement, choices )
66
+ choices.map! do |choice|
67
+ choice.is_a?(String) ? [choice] : choice # I'm being too clever by half here. .first/.last still works.
68
+ end
69
+
70
+ choice_text = ""
71
+ choices.each_with_index do |choice,i|
72
+ choice_text << "\t\t#{i}) #{choice.first}\n"
73
+ end
74
+
75
+ selection = ask( "#{statement}\n\tChoices:\n#{choice_text}>>> ".paint(:blue) )
76
+ choices[selection.to_i].last
77
+ end
78
+
79
+ def ask_prettily( question, *args )
80
+ ask( question.paint(:blue), *args )
81
+ end
82
+
83
+ def say_all_is_well( statement )
84
+ say( statement, :green )
85
+ end
86
+
87
+ def say_error( statement )
88
+ say( statement.paint(:bg_red, :bold) )
89
+ end
90
+
91
+ end
92
+ end
93
+ end