Skip to content

Commit

Permalink
[Bin] Extracted option parsing handling from the CocoaPods gem.
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiopelosin committed Oct 20, 2012
1 parent 6c3d04a commit b5381c3
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 91 deletions.
2 changes: 2 additions & 0 deletions Gemfile.lock
Expand Up @@ -3,6 +3,7 @@ PATH
specs:
xcodeproj (0.3.5)
activesupport (~> 3.2.6)
colored (~> 1.2)

GEM
remote: http://rubygems.org/
Expand All @@ -11,6 +12,7 @@ GEM
i18n (~> 0.6)
multi_json (~> 1.0)
bacon (1.1.0)
colored (1.2)
ffi (1.1.5)
github-markup (0.7.4)
i18n (0.6.1)
Expand Down
95 changes: 4 additions & 91 deletions bin/xcodeproj
@@ -1,100 +1,13 @@
#!/usr/bin/env ruby

if $0 == __FILE__
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
require "rubygems"
require "bundler/setup"
$:.unshift File.expand_path('../../ext', __FILE__)
$:.unshift File.expand_path('../../lib', __FILE__)
end

require 'xcodeproj'

require 'optparse'

module Xcodeproj
class Bin
def initialize(argv)
@argv = parse_options!(argv)
end

def run
case @argv.shift
when 'targets-diff'
targets_diff
else
puts @option_parser
end
end

protected

def xcodeproj_path
unless @xcodeproj_path
projects = Dir.glob('*.xcodeproj')
if projects.size == 1
xcodeproj_path = projects.first
elsif projects.size > 1
invalid_command('There are more than one Xcode project documents ' \
'in the current working directory. Please specify ' \
'which to use with the `--project` option.')
else
invalid_command('No Xcode project document found in the current ' \
'working directory. Please specify which to use ' \
'with the `--project` option.')
end
@xcodeproj_path = File.expand_path(xcodeproj_path)
end
@xcodeproj_path
end

def xcodeproj
@xcodeproj ||= Project.new(xcodeproj_path)
end

def targets_diff
require 'yaml'
differ = Helper::TargetDiff.new(xcodeproj, @argv[0], @argv[1])
files = differ.new_source_build_files.map do |build_file|
{
'Name' => build_file.file_ref.name,
'Path' => build_file.file_ref.path,
'Build settings' => build_file.settings,
}
end
puts files.to_yaml
end

private

def invalid_command(msg)
puts msg
exit 1
end

def parse_options!(argv)
@option_parser = OptionParser.new do |opts|
opts.banner = "Usage: xcodeproj [command] [options]"
opts.separator ""
opts.separator "Commands:"
opts.separator ""
opts.separator " targets-diff [target 1] [target 2]\tShows the difference between two targets. (Only build source files atm.)"
opts.separator ""

opts.separator "Options:"
opts.separator ""

opts.on('--project PATH', "The Xcode project document to use.") do |xcodeproj_path|
@xcodeproj_path = File.expand_path(xcodeproj_path)
end

opts.on("--version", "Show xcodeproj version.") do |v|
puts Xcodeproj::VERSION
exit
end
end
remainder = argv.dup
@option_parser.parse!(remainder)
remainder
end
end
end

Xcodeproj::Bin.new(ARGV).run
Xcodeproj::Command.run(*ARGV)
11 changes: 11 additions & 0 deletions lib/xcodeproj.rb
@@ -1,7 +1,18 @@
module Xcodeproj
VERSION = '0.3.5'

require 'colored'
class PlainInformative < StandardError
end

class Informative < PlainInformative
def message
super !~ /\[!\]/ ? "[!] #{super}\n".red : super
end
end

autoload :Config, 'xcodeproj/config'
autoload :Command, 'xcodeproj/command'
autoload :Constants, 'xcodeproj/constants'
autoload :Helper, 'xcodeproj/helper'
autoload :Project, 'xcodeproj/project'
Expand Down
43 changes: 43 additions & 0 deletions lib/xcodeproj/Command/target_diff.rb
@@ -0,0 +1,43 @@
module Xcodeproj
class Command
class TargetDiff < Command
def self.banner
%{Installing dependencies of a project:
$ targets-diff [target 1] [target 2]
Shows the difference between two targets. (Only build source files atm.)
}
end

def self.options
[
["--project PATH", "The Xcode project document to use."],
].concat(super)
end

def initialize(argv)
@target1 = argv.shift_argument
@target2 = argv.shift_argument
if argv.option('--project')
@xcodeproj_path = File.expand_path(argv.shift_argument)
end
super unless argv.empty?
end

def run
require 'yaml'
differ = Helper::TargetDiff.new(xcodeproj, @target1, @target2)
files = differ.new_source_build_files.map do |build_file|
{
'Name' => build_file.file_ref.name,
'Path' => build_file.file_ref.path,
'Build settings' => build_file.settings,
}
end
puts files.to_yaml
end
end
end
end

127 changes: 127 additions & 0 deletions lib/xcodeproj/command.rb
@@ -0,0 +1,127 @@
module Xcodeproj

class Command
autoload :TargetDiff, 'xcodeproj/command/target_diff'
autoload :ProjectDiff,'xcodeproj/command/project_diff'

class Help < StandardError
def initialize(command_class, argv, unrecognized_command = nil)
@command_class, @argv, @unrecognized_command = command_class, argv, unrecognized_command
end

def message
message = [
'',
@command_class.banner.gsub(/\$ pod (.*)/, '$ pod \1'.green),
'',
'Options:',
'',
options,
"\n",
].join("\n")
message << "[!] Unrecognized command: `#{@unrecognized_command}'\n".red if @unrecognized_command
message << "[!] Unrecognized argument#{@argv.count > 1 ? 's' : ''}: `#{@argv.join(' - ')}'\n".red unless @argv.empty?
message
end

private

def options
options = @command_class.options
keys = options.map(&:first)
key_size = keys.inject(0) { |size, key| key.size > size ? key.size : size }
options.map { |key, desc| " #{key.ljust(key_size)} #{desc}" }.join("\n")
end
end

class ARGV < Array
def options; select { |x| x.to_s[0,1] == '-' }; end
def arguments; self - options; end
def option(name); !!delete(name); end
def shift_argument; (arg = arguments[0]) && delete(arg); end
end

def self.banner
commands = ['target-diff', 'project-diff']
banner = "To see help for the available commands run:\n\n"
banner + commands.map { |cmd| " * $ xcodeproj #{cmd.green} --help" }.join("\n")
end

def self.options
[
['--help', 'Show help information'],
# ['--silent', 'Print nothing'],
# ['--no-color', 'Print output without color'],
# ['--verbose', 'Print more information while working'],
['--version', 'Prints the version of CocoaPods'],
]
end

def self.run(*argv)
sub_command = parse(*argv)
sub_command.run

rescue Interrupt
puts "[!] Cancelled".red
Config.instance.verbose? ? raise : exit(1)

rescue Exception => e
puts e.message
puts *e.backtrace
exit 1
end

def self.parse(*argv)
argv = ARGV.new(argv)
if argv.option('--version')
puts VERSION
exit!(0)
end

show_help = argv.option('--help')

String.send(:define_method, :colorize) { |string , _| string } if argv.option( '--no-color' )

command_class = case command_argument = argv.shift_argument
when 'target-diff' then TargetDiff
when 'project-diff' then ProjectDiff
end

if command_class.nil?
raise Help.new(self, argv, command_argument)
elsif show_help
raise Help.new(command_class, argv)
else
command_class.new(argv)
end
end

def initialize(argv)
raise Help.new(self.class, argv)
end

def xcodeproj_path
unless @xcodeproj_path
projects = Dir.glob('*.xcodeproj')
if projects.size == 1
xcodeproj_path = projects.first
elsif projects.size > 1
raise Informative, 'There are more than one Xcode project documents ' \
'in the current working directory. Please specify ' \
'which to use with the `--project` option.'
else
raise Informative, 'No Xcode project document found in the current ' \
'working directory. Please specify which to use ' \
'with the `--project` option.'
end
@xcodeproj_path = File.expand_path(xcodeproj_path)
end
@xcodeproj_path
end

def xcodeproj
@xcodeproj ||= Project.new(xcodeproj_path)
end
end
end

1 change: 1 addition & 0 deletions xcodeproj.gemspec
Expand Up @@ -22,6 +22,7 @@ Gem::Specification.new do |s|
s.require_paths = %w{ ext lib }

s.add_runtime_dependency 'activesupport', '~> 3.2.6'
s.add_runtime_dependency 'colored', '~> 1.2'

## Make sure you can build the gem on older versions of RubyGems too:
s.rubygems_version = "1.6.2"
Expand Down

0 comments on commit b5381c3

Please sign in to comment.