Class: SC::Tools

Inherits:
Thor show all
Defined in:
lib/sproutcore/tools.rb,
lib/sproutcore/tools/gen.rb,
lib/sproutcore/tools/docs.rb,
lib/sproutcore/tools/init.rb,
lib/sproutcore/tools/build.rb,
lib/sproutcore/tools/server.rb,
lib/sproutcore/tools/phantom.rb,
lib/sproutcore/tools/manifest.rb,
lib/sproutcore/tools/build_number.rb

Overview

Generates components for SproutCore. The generator allows the user to quickly set up a SproutCore framework using any of the built in templates such as the project itself, apps, models, views, controllers and more

The template files will be copied to their target location and also be parsed through the Erubis templating system. Template file paths can contain instance variables in the form of class_name which in turn would be the value of class_name once generated.

To develop a new generator, you can add it to the sproutcore/gen/ directory with the following file structure:

gen/
  <generator_name>/   - singular directory name of the generator
     Buildfile        - contains all config options and build tasks
     README           - prints when generator is done
     templates/       - contains all the files you want to generate
     USAGE            - prints when user gives uses --help option

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeTools

This is the core entry method used to run every tool. Extend this method with any standard preprocessing you want all tools to do before they do their specific thing.



69
70
71
72
73
74
75
76
# File 'lib/sproutcore/tools.rb', line 69

def initialize(*)
  super
  prepare_logger!
  prepare_mode!
  dont_minify!
  prepare_app!
  prepare_build_numbers!
end

Class Method Details

.invoke(task_name) ⇒ Object



29
30
31
# File 'lib/sproutcore/tools.rb', line 29

def self.invoke(task_name)
  start([task_name.to_s] + ARGV)
end

Instance Method Details



53
54
55
56
57
58
# File 'lib/sproutcore/tools.rb', line 53

def banner
  str = "SproutCore #{SC::VERSION} Usage"
  puts "#{str}\n"+('='*str.length)+"\n\n"

  help
end

#build(*targets) ⇒ Object



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
141
142
143
144
145
146
# File 'lib/sproutcore/tools/build.rb', line 48

def build(*targets)
  if options.help
    help('build')
    return
  end

  t1 = Time.now
  SC.logger.info  'Starting build process...'
  # Copy some key props to the env
  SC.env.whitelist_name = options.whitelist
  SC.env.blacklist_name = options.blacklist
  SC.env.accept_name    = options.accept
  SC.env.build_prefix   = options.buildroot if options.buildroot
  SC.env.staging_prefix = options.stageroot if options.stageroot
  SC.env.use_symlink    = options.symlink

  # Get entries option
  entry_filters = nil
  if options[:entries]
    entry_filters = options[:entries].split(',')
  end

  # We want Chance to clear files like sprites immediately after they're asked for,
  # because we'll only need them once during a build.
  Chance.clear_files_immediately

  # Get the manifests to build
  manifests = build_manifests(*targets) do |manifest|
    # This is our own logic to prevent processing a manifest twice
    next if manifest[:built_by_builder]
    manifest[:built_by_builder] = true

    # get entries.  If "entries" option was specified, use to filter
    # filename.  Must match end of filename.
    entries = manifest.entries
    if entry_filters
      entries = entries.select do |entry|
        is_allowed = false
        entry_filters.each do |filter|
          is_allowed = entry.filename =~ /#{filter}$/
          break if is_allowed
        end
        is_allowed
      end
    end

    # if there are entries to build, log and build
    build_entries_for_manifest manifest, options.allow_commented_js

    # Build dependencies
    target = manifest.target
    required = target.expand_required_targets :theme => true,
      :debug => target.config.load_debug,
      :tests => target.config.load_tests,

      # Modules are not 'required' technically, as they may be loaded
      # lazily. However, we want to know all targets that should be built,
      # so we'll include modules as well.
      :modules => true


    required.each {|t|
      m = t.manifest_for(manifest.variation)


      # And, yes, the same as above. We're just building entries for all required targets.
      # We're also going to mark them as fully-built so they don't get built again.
      next if m[:built_by_builder]
      m[:built_by_builder] = true
      m.build!

      build_entries_for_manifest m, options.allow_commented_js


    }

    # Clean up
    manifest.reset!
    Chance::ChanceFactory.clear_instances
  end

  # The HTML5 manifest generator does not work properly; it is unstable (can cause crashes)
  # and won't pick up modules. We need an alternative implemenation, preferably one that uses
  # Abbot's own manifests to figure out what files are required. This is non-trivial, however.
  #
  # if $to_html5_manifest.length > 0
  #   $to_html5_manifest.each do |entry|
  #     SC::Helpers::HTML5Manifest.new.build(entry)
  #   end
  # end

  SC::Helpers::Minifier.wait

  t2 = Time.now
  seconds = t2-t1
  minutes = seconds/60
  seconds = seconds%60
  puts 'Build time: '+minutes.floor.to_s+ ' minutes '+seconds.floor.to_s+' secs'
end

#build_number(*targets) ⇒ Object



17
18
19
20
# File 'lib/sproutcore/tools/build_number.rb', line 17

def build_number(*targets)
  target = requires_target!(*targets)
  $stdout << target.prepare![:build_number]
end

#docsObject



14
15
16
# File 'lib/sproutcore/tools/docs.rb', line 14

def docs
  puts "Doc generation is no longer bundled with SproutCore. Please install the sc-docs tool instead."
end

#gen(*arguments) ⇒ Object



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
# File 'lib/sproutcore/tools/gen.rb', line 60

def gen(*arguments)
  return show_help if arguments.empty?

  # backwards compatibility case: client is a synonym for 'app'
  name = arguments[0]=='client' ? 'app' : arguments[0]

  # The --statechart switch uses a different app or project generator
  if name == 'app' && options[:statechart]
    name = 'statechart_app'
  end

  # Load generator
  generator_project = self.project || SC.builtin_project
  generator = generator_project.generator_for name,
    :arguments   => arguments,
    :filename    => options[:filename],
    :target_name => options[:target],
    :dry_run     => options[:"dry-run"],
    :force       => options[:force],
    :statechart  => options[:statechart]

  # if no generator could be found, or if we just asked to show help,
  # just return the help...
  return show_help(name, generator) if generator.nil? || options[:help]

  begin
    # Prepare generator and then log some debug info
    generator.prepare!
    info "Loading generator Buildfile at: #{generator.buildfile.loaded_paths.last}"

    debug "\nSETTINGS"
    generator.each { |k,v| debug("#{k}: #{v}") }

    # Now, run the generator
    generator.build!

  rescue Exception => error_message
    warn "For specific help on how to use this generator, type: sc-gen #{name} --help"
    fatal! error_message.to_s
  end

  SC.logger << "\n"
  generator.log_readme
  return 0
end

#init(project_name, app_name = nil) ⇒ Object



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
# File 'lib/sproutcore/tools/init.rb', line 14

def init(project_name, app_name=nil)

# Generate the project
 project_gen = SC.builtin_project.generator_for 'project',
  :arguments => ['project', project_name],
  :dry_run   => options[:"dry-run"],
  :force     => options[:force]

 project_gen.prepare!.build!

  # Next, get the project root & app name
  project_root = project_gen.build_root / project_gen.filename
  app_name = project_gen.filename if app_name.nil?

  # And get the app generator and run it
  project = SC::Project.load project_root, :parent => SC.builtin_project

  # Use the statechart_app generator if --statechart is provided
  app_type = options[:statechart] ? 'statechart_app' : 'app'

  generator = project.generator_for app_type,
    :arguments => ['app', app_name],
    :dry_run   => options[:"dry-run"],
    :force     => options[:force]
  generator.prepare!.build!

  project_gen.log_file(project_gen.source_root / 'INIT')
  return 0
end

#manifest(*targets) ⇒ Object



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
# File 'lib/sproutcore/tools/manifest.rb', line 34

def manifest(*targets)

  # Copy some key props to the env
  SC.env.build_prefix   = options.buildroot if options.buildroot
  SC.env.staging_prefix = options.stageroot if options.stageroot
  SC.env.use_symlink    = options.symlink

  # Verify format
  format = (options.format || 'yaml').to_s.downcase.to_sym
  if ![:yaml, :json].include?(format)
    raise "Format must be yaml or json"
  end

  # Get allowed keys
  only_keys   = Tools.get_allowed_keys(options[:only])
  except_keys = Tools.get_allowed_keys(options[:except])

  # call core method to actually build the manifests...
  manifests = build_manifests(*targets)

  # now convert them to hashes...
  manifests.map! do |manifest|
    manifest.to_hash :hidden => options.hidden,
      :only => only_keys, :except => except_keys
  end

  # Serialize'em
  case format
  when :yaml
    output = ["# SproutCore Build Manifest v1.0", manifests.to_yaml].join("\n")
  when :json
    output = mainfests.to_json
  end

  # output ...
  if options.output
    file = File.open(options.output, 'w')
    file.write(output)
    file.close
  else
    $stdout << output
  end

end

#phantom(*args) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/sproutcore/tools/phantom.rb', line 16

def phantom(*args)
  result = false
  target = find_targets('/sproutcore').first

  if target
    test_runner_path = File.expand_path(File.join('phantomjs', 'test_runner.js'), target.source_root)
    if File.file? test_runner_path
      result = system "phantomjs #{test_runner_path} #{args.join(' ')}"
    else
      SC.logger.fatal "Could not find PhantomJS test runner"
    end
  else
    SC.logger.fatal "Could not find /sproutcore target"
  end

  exit(1) unless result
end

#serverObject



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
# File 'lib/sproutcore/tools/server.rb', line 38

def server
  if options.help
    help('server')
    return
  end
  
  prepare_mode!('debug') # set mode again, using debug as default

  SC.env[:build_prefix]   = options[:buildroot] if options[:buildroot]
  SC.env[:staging_prefix] = options[:stageroot] if options[:stageroot]
  SC.env[:whitelist_name] = options.whitelist
  SC.env[:blacklist_name] = options.blacklist
  SC.env[:accept_name]    = options.accept

  # get project and start service.
  project = requires_project!

  # start shell if passed
  if options[:irb]
    require 'irb'
    require 'irb/completion'
    if File.exists? ".irbrc"
      ENV['IRBRC'] = ".irbrc"
    end

    SC.project = project
    SC.logger << "SproutCore v#{SC::VERSION} Interactive Shell\n"
    SC.logger << "SC.project = #{project.project_root}\n"
    ARGV.clear # do not pass onto IRB
    IRB.start
  else
    SC.logger << "SproutCore v#{SC::VERSION} Development Server\n"
    begin
      SC::Rack::Service.start(options.merge(:project => project))
    rescue => e
      if e.message =~ /no acceptor/
        raise "No acceptor. Most likely the port is already in use. Try using --port to specify a different port."
      else
        raise e
      end
    end
  end
end

#versionObject



62
63
64
# File 'lib/sproutcore/tools.rb', line 62

def version
  puts "SproutCore #{SC::VERSION}"
end