aboutsummaryrefslogtreecommitdiffstats
path: root/railties/lib/rails_generator/options.rb
blob: fe80f8340dadd5011ca7d4c1785a74af5e527919 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
require 'optparse'

module Rails
  module Generator
    module Options
      def self.append_features(base)
        super
        base.extend(ClassMethods)
        class << base
          if respond_to?(:inherited)
            alias_method :inherited_without_options, :inherited
          end
          alias_method :inherited, :inherited_with_options
        end
      end

      module ClassMethods
        def inherited_with_options(sub)
          inherited_without_options(sub) if respond_to?(:inherited_without_options)
          sub.extend(Rails::Generator::Options::ClassMethods)
        end

        def mandatory_options(options = nil)
          if options
            write_inheritable_attribute(:mandatory_options, options)
          else
            read_inheritable_attribute(:mandatory_options) or write_inheritable_attribute(:mandatory_options, {})
          end
        end

        def default_options(options = nil)
          if options
            write_inheritable_attribute(:default_options, options)
          else
            read_inheritable_attribute(:default_options) or write_inheritable_attribute(:default_options, {})
          end
        end

        # Merge together our class options.  In increasing precedence:
        #   default_options   (class default options)
        #   runtime_options   (provided as argument)
        #   mandatory_options (class mandatory options)
        def full_options(runtime_options = {})
          default_options.merge(runtime_options).merge(mandatory_options)
        end

      end

      # Each instance has an options hash that's populated by #parse.
      def options
        @options ||= {}
      end
      attr_writer :options

      protected
        # Convenient access to class mandatory options.
        def mandatory_options
          self.class.mandatory_options
        end

        # Convenient access to class default options.
        def default_options
          self.class.default_options
        end

        # Merge together our instance options.  In increasing precedence:
        #   default_options   (class default options)
        #   options           (instance options)
        #   runtime_options   (provided as argument)
        #   mandatory_options (class mandatory options)
        def full_options(runtime_options = {})
          self.class.full_options(options.merge(runtime_options))
        end

        # Parse arguments into the options hash.  Classes may customize
        # parsing behavior by overriding these methods:
        #   #banner                 Usage: ./script/generate [options]
        #   #add_options!           Options:
        #                             some options..
        #   #add_general_options!   General Options:
        #                             general options..
        def parse!(args, runtime_options = {})
          self.options = {}

          @option_parser = OptionParser.new do |opt|
            opt.banner = banner
            add_options!(opt)
            add_general_options!(opt)
            opt.parse!(args)
          end

          return args
        ensure
          self.options = full_options(runtime_options)
        end

        # Raise a usage error.  Override usage_message to provide a blurb
        # after the option parser summary.
        def usage(message = usage_message)
          raise UsageError, "#{@option_parser}\n#{message}"
        end

        def usage_message
          ''
        end

        # Override with your own usage banner.
        def banner
          "Usage: #{$0} [options]"
        end

        # Override to add your options to the parser:
        #   def add_options!(opt)
        #     opt.on('-v', '--verbose') { |value| options[:verbose] = value }
        #   end
        def add_options!(opt)
        end

        # Adds general options like -h and --quiet.  Usually don't override.
        def add_general_options!(opt)
          opt.separator ''
          opt.separator 'General Options:'

          opt.on('-p', '--pretend', 'Run but do not make any changes.') { |options[:pretend]| }
          opt.on('-f', '--force', 'Overwrite files that already exist.') { options[:collision] = :force }
          opt.on('-s', '--skip', 'Skip files that already exist.') { options[:collision] = :skip }
          opt.on('-q', '--quiet', 'Suppress normal output.') { |options[:quiet]| }
          opt.on('-t', '--backtrace', 'Debugging: show backtrace on errors.') { |options[:backtrace]| }
          opt.on('-h', '--help', 'Show this help message.') { |options[:help]| }
          opt.on('-c', '--svn', 'Modify files with subversion. (Note: svn must be in path)') do
            options[:svn] = `svn status`.inject({}) do |opt, e|
              opt[e.chomp[7..-1]] = true
              opt
            end
          end
        end

    end
  end
end