ovaltine 1.0.2 → 1.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: bf29e84c1f9fcf6bf4121916abd32252f21bcf11
4
- data.tar.gz: 45c7913c46c4044da01ea1910ac0223177ab63b7
5
2
  SHA512:
6
- metadata.gz: 94aac6bb2aff88696a796823c8a2caf5f9899d63a154da2b93cd354740365a98ad4e725bd9a10a8d5742861314693080439a24c1012fac9613eeecab9f3651c5
7
- data.tar.gz: ebf734f231c593d20dbccbaec111744af471beb63524479efe86a2781ec6c1cbc587444d3c3a10cbc83678a9c6fffccc231f596a8a2704300832abb58e0eb9e7
3
+ data.tar.gz: f76c243272bd421a5635d495d6796d4820688d624d322d7c2a3994e920c65d3b3ddea40f08fe6fcec1fe66973c963c1ca830cf6a1f5c91a64192c56d461f6442
4
+ metadata.gz: da7d8f1f5a64d059b5b62bc76847df9d3ff7c595c2df30147b9747aacaed3e4b60391f61c0b0b72bdf8f07688dc00ef8e9b761bcde085b898409eedb506daac1
5
+ SHA1:
6
+ data.tar.gz: 88b8b643bcc95048a2e41e9e970bbe10d68311be
7
+ metadata.gz: 96b9c29b9c0754d1065ddc765524a428a409978a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ # 1.0.4
2
+
3
+ - Hotfix for failed error handling in Ruby 1.8.7
4
+ - Avoid writing xcode project files when no files added
5
+ - Add language argument for potentially generating templates in other languages
6
+ - Prefix identifier constants
7
+
8
+ # 1.0.3
9
+
10
+ - Experimental support for adding generated files to Xcode project
11
+
1
12
  # 1.0.2
2
13
 
3
14
  - Hotfix for Ruby 1.8.7
data/Gemfile.lock ADDED
@@ -0,0 +1,19 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ovaltine (1.0.3)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ bacon (1.2.0)
10
+ rake (10.3.2)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ bacon (~> 1.2)
17
+ bundler (~> 1.3)
18
+ ovaltine!
19
+ rake (~> 10.0)
data/README.md CHANGED
@@ -1,15 +1,25 @@
1
- # Ovaltine
1
+ # Ovaltine [![Build Status](https://travis-ci.org/kattrali/ovaltine.svg?branch=master)](https://travis-ci.org/kattrali/ovaltine)
2
2
 
3
3
  The chocolatey treat which makes your code clean! Yum!
4
4
 
5
5
  `Ovaltine` scans your `storyboard` files and generates constant files for view controller, segue, and reuse identifiers. For instance, if you have a storyboard called `Main` and a view controller with the Storyboard ID `authenticationViewController`, then you can instantiate that controller with something like `[ABCMainStoryboard instantiateAuthenticationViewController]`. No mistyping, plenty of chocolately goodness.
6
6
 
7
- # Installation
7
+ ## Installation
8
8
 
9
9
  ```
10
10
  gem install ovaltine
11
11
  ```
12
12
 
13
- # Usage
13
+ ## Example Usage
14
14
 
15
- Run `ovaltine` from the command line
15
+ ```
16
+ ovaltine --prefix ABC --auto-replace --auto-add --project path/to/project.xcodeproj path/to/project/files
17
+ ```
18
+
19
+ Run from the command line or as a build step (if you are brave!) [Here](https://gist.github.com/kattrali/bbe9e2464d02a8ca4cb1) are some example files generated using `ovaltine`.
20
+
21
+ ## Additional Documentation
22
+
23
+ ```
24
+ ovaltine --help
25
+ ```
data/Rakefile CHANGED
@@ -2,4 +2,4 @@
2
2
  desc "Run unit tests"
3
3
  task :spec do
4
4
  sh 'bacon specs/*_spec.rb'
5
- end
5
+ end
data/TODO.md CHANGED
@@ -1,6 +1,5 @@
1
1
 
2
2
  ## TODO
3
3
 
4
- * Support adding generated files to projects (with minimal dependencies, for easier tool integration)
5
4
  * Add switch for language preferences
6
- * Add support for OS X storyboards
5
+ * Add support for OS X storyboards
data/bin/ovaltine CHANGED
@@ -12,8 +12,8 @@ require 'ovaltine'
12
12
  require 'optparse'
13
13
 
14
14
  parser_options = {
15
- :output_directory => '.',
16
- :prefix => ''
15
+ :prefix => '',
16
+ :language => 'objc'
17
17
  }
18
18
 
19
19
  def exit_with_error(message)
@@ -29,7 +29,7 @@ OptionParser.new do |opts|
29
29
  opts.on('-o', '--output DIR', 'Specify output directory. Default is pwd') do |path|
30
30
  parser_options[:output_directory] = path
31
31
  end
32
- opts.on('--prefix PREFIX', 'Class prefix for generated files') do |prefix|
32
+ opts.on('--prefix PREFIX', 'Specify class prefix for generated files') do |prefix|
33
33
  parser_options[:prefix] = prefix
34
34
  end
35
35
  opts.on('--auto-add', 'Automatically add generated files to the Xcode project') do
@@ -38,6 +38,9 @@ OptionParser.new do |opts|
38
38
  opts.on('--auto-replace', 'Automatically replace files with the same name as generated files') do
39
39
  parser_options[:auto_replace] = true
40
40
  end
41
+ opts.on('--objc', 'Specify Objective-C as the template language (Default)') do
42
+ parser_options[:language] = 'objc'
43
+ end
41
44
  opts.on_tail('-h', '--help', 'Show this message') { puts opts; exit }
42
45
  opts.on_tail("-v", "--version", "Show version") { puts Ovaltine::VERSION; exit }
43
46
  opts.parse!
@@ -103,7 +103,7 @@ module Ovaltine
103
103
  end
104
104
 
105
105
  def variable_name identifier
106
- "_#{identifier.gsub(/\W/,'').gsub(/\b\w/){ $&.downcase }}"
106
+ "_#{@prefix}#{identifier.gsub(/\W/,'').gsub(/\b\w/){ $&.downcase }}"
107
107
  end
108
108
 
109
109
 
@@ -20,7 +20,7 @@ module Ovaltine
20
20
 
21
21
  #import <Foundation/Foundation.h>
22
22
 
23
- @interface {CLASS_NAME}
23
+ @interface {CLASS_NAME} : NSObject
24
24
 
25
25
  +(UIStoryboard *)storyboard;
26
26
 
@@ -40,7 +40,7 @@ module Ovaltine
40
40
  #import <UIKit/UIKit.h>
41
41
  #import "{CLASS_NAME}.h"
42
42
 
43
- static UIStoryboard* _storyboard = nil;
43
+ static UIStoryboard *_storyboard = nil;
44
44
  {STATIC_VARIABLES}
45
45
 
46
46
  @implementation {CLASS_NAME}
@@ -1,3 +1,3 @@
1
1
  module Ovaltine
2
- VERSION = "1.0.2"
2
+ VERSION = "1.0.4"
3
3
  end
@@ -0,0 +1,19 @@
1
+ class String
2
+ def to_plist
3
+ to_json
4
+ end
5
+ end
6
+
7
+ class Array
8
+ def to_plist
9
+ items = map { |item| "#{item.to_plist}" }
10
+ "( #{items.join ","} )"
11
+ end
12
+ end
13
+
14
+ class Hash
15
+ def to_plist
16
+ items = map { |key, value| "#{key.to_plist} = #{value.to_plist};\n" }
17
+ "{ #{items.join} }"
18
+ end
19
+ end
@@ -0,0 +1,14 @@
1
+
2
+ module Ovaltine
3
+ class XcodeProject
4
+ class PBXFileReference < PBXObject
5
+ def self.create path, file_type
6
+ self.new PBXObject.create_uuid, {
7
+ "sourceTree" => "<group>",
8
+ "path" => path,
9
+ "lastKnownFileType" => file_type
10
+ }
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,41 @@
1
+
2
+ module Ovaltine
3
+ class XcodeProject
4
+ class PBXGroup < PBXObject
5
+
6
+ def self.create name
7
+ self.new(PBXObject.create_uuid, {
8
+ "children" => [],
9
+ "name" => name,
10
+ "sourceTree" => "<group>"
11
+ })
12
+ end
13
+
14
+ def add_object obj
15
+ unless self["children"].include?(obj.uuid)
16
+ self["children"] << obj.uuid
17
+ end
18
+ end
19
+
20
+ def children recursive=false
21
+ children = self.project_file.objects_with_uuids self["children"]
22
+
23
+ if recursive
24
+ subgroups = PBXObject.filter children, { "isa" => "PBXGroup" }
25
+ subgroups.each { |subgroup| children << subgroup.children(true) }
26
+ end
27
+
28
+ children.flatten
29
+ end
30
+ end
31
+
32
+ class PBXSourcesBuildPhase < PBXObject; end
33
+ class PBXFrameworksBuildPhase < PBXObject; end
34
+ class PBXResourcesBuildPhase < PBXObject; end
35
+ class PBXNativeTarget < PBXObject; end
36
+ class PBXProject < PBXObject; end
37
+ class PBXContainerItemProxy < PBXObject; end
38
+ class PBXReferenceProxy < PBXObject; end
39
+ class XCBuildConfiguration < PBXObject; end
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+
2
+ module Ovaltine
3
+ class XcodeProject
4
+ class PBXObject < Hash
5
+ attr_accessor :project_file
6
+ attr_reader :uuid
7
+
8
+ def self.filter array, attrs
9
+ array.select do |obj|
10
+ attrs.select { |k,v| obj[k] == v }.length == attrs.length
11
+ end
12
+ end
13
+
14
+ def self.create_uuid
15
+ uuid = ""
16
+ 24.times { uuid += "0123456789ABCDEF"[rand(16),1] }
17
+ uuid
18
+ end
19
+
20
+ def initialize uuid, hash
21
+ @project = nil
22
+ @uuid = uuid
23
+ self["isa"] = self.class.to_s.split('::').last
24
+ hash.each { |k,v| self[k] = v }
25
+ end
26
+
27
+ def inspect
28
+ @uuid + "=" + super
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,104 @@
1
+
2
+ module Ovaltine
3
+ class XcodeProject
4
+
5
+ def load_dependencies
6
+ unless @@loaded ||= false
7
+ unless Object.const_defined?(:JSON)
8
+ begin
9
+ require 'json'
10
+ rescue LoadError
11
+ require File.expand_path(File.join(File.dirname(__FILE__),'../../vendor/json_pure/parser'))
12
+ require File.expand_path(File.join(File.dirname(__FILE__),'../../vendor/json_pure/generator'))
13
+ end
14
+ end
15
+ @@loaded = true
16
+ end
17
+ end
18
+
19
+ def initialize path
20
+ load_dependencies
21
+ if path =~ /\.xcodeproj$/
22
+ @path = File.join(path, 'project.pbxproj')
23
+ else
24
+ @path = path
25
+ end
26
+ @json = JSON.parse(`plutil -convert json -o - "#{@path}"`)
27
+
28
+ @json["objects"].each do |uuid, hash|
29
+ klass = PBXObject
30
+ begin
31
+ klass = Ovaltine::XcodeProject.const_get "#{hash['isa']}"
32
+ rescue
33
+ end
34
+
35
+ obj = klass.new uuid, hash
36
+ obj.project_file = self
37
+
38
+ @json["objects"][uuid] = obj
39
+ end
40
+ end
41
+
42
+ def save
43
+ File.open(@path, "w") { |f| f.write @json.to_plist }
44
+ end
45
+
46
+ def objects
47
+ @json["objects"].values
48
+ end
49
+
50
+ def groups
51
+ objects_of_class(PBXGroup)
52
+ end
53
+
54
+ def files
55
+ objects_of_class(PBXFileReference)
56
+ end
57
+
58
+ def objects_of_class klass
59
+ str = klass.to_s.split('::').last
60
+ objects.select {|obj| obj["isa"] == str }
61
+ end
62
+
63
+ def objects_with_uuids uuids
64
+ uuids.map {|uuid| self.object_with_uuid uuid }
65
+ end
66
+
67
+ def object_with_uuid uuid
68
+ @json["objects"][uuid]
69
+ end
70
+
71
+ def add_file_ref path
72
+ relpath = File.expand_path(path).gsub(File.dirname(File.dirname(File.expand_path(@path))), '')[1..-1]
73
+ relpath = relpath[(relpath.index('/') + 1)..-1]
74
+ return nil if files.detect {|ref| ref["path"] == relpath}
75
+ ref = PBXFileReference.create(relpath, file_type(path))
76
+ add_object(ref)
77
+ main_group = groups.detect do |g|
78
+ !g["name"] && g["path"] && !g["path"].include?("Test")
79
+ end
80
+ unless group = groups.detect {|g| g["name"] == "Generated Files"}
81
+ group = PBXGroup.create("Generated Files")
82
+ add_object(group)
83
+ main_group.add_object(group)
84
+ end
85
+ group.add_object(ref)
86
+ ref
87
+ end
88
+
89
+ def add_object obj
90
+ obj.project_file = self
91
+ @json["objects"][obj.uuid] = obj
92
+ end
93
+
94
+ def file_type path
95
+ file_type = 'sourcecode'
96
+ if path =~ /\.m$/
97
+ file_type = 'sourcecode.c.objc'
98
+ elsif path =~ /\.h$/
99
+ file_type = 'sourcecode.c.h'
100
+ end
101
+ file_type
102
+ end
103
+ end
104
+ end
data/lib/ovaltine.rb CHANGED
@@ -1,25 +1,38 @@
1
1
 
2
2
  require 'ovaltine/storyboard'
3
- require 'ovaltine/objc/storyboard_formatter'
4
- require 'ovaltine/objc/storyboard_templates'
5
3
  require 'ovaltine/version'
4
+ require 'ovaltine/xcode_project'
5
+ require 'ovaltine/xcode_project/pbxobject'
6
+ require 'ovaltine/xcode_project/pbxgroup'
7
+ require 'ovaltine/xcode_project/pbxfilereference'
8
+ require 'ovaltine/xcode_project/ext/stdlib'
6
9
 
7
10
  module Ovaltine
8
11
 
9
12
  def self.create_constant_files(path, options)
13
+ require_formatter(options[:language])
10
14
  files = Dir.glob("#{path}/**/*.storyboard")
11
15
  groups = files.group_by {|f| File.basename(f).sub('.storyboard','')}
12
16
  formatters = groups.map do |name, paths|
13
17
  storyboard = Storyboard.new(name, paths)
14
- StoryboardFormatter.new(storyboard, options[:prefix], options[:output_directory])
18
+ StoryboardFormatter.new(storyboard, options[:prefix], (options[:output_directory] || path))
15
19
  end
16
20
  generated_paths = formatters.map(&:output_paths).flatten
17
- if path = generated_paths.detect {|p| File.exist?(p)} and !options[:auto_replace]
18
- if prompt("Some generated files already exist. Overwrite? (Y/n)", 'y')
19
- write_files(formatters)
21
+ if existing_path = generated_paths.detect {|p| File.exist?(p)} and !options[:auto_replace]
22
+ return unless prompt("Some generated files already exist. Overwrite? (Y/n)", 'y')
23
+ end
24
+
25
+ paths = write_files(formatters)
26
+
27
+ if project_filepath = options[:project] || Dir.glob("#{File.dirname(path)}/**/*.xcodeproj").first
28
+ return unless options[:auto_add] or prompt("[Experimental] Add files to project? (y/N)", 'n')
29
+ project = XcodeProject.new(project_filepath)
30
+ if paths.sort.map {|p| project.add_file_ref(p)}.compact.size > 0
31
+ project.save
32
+ puts "#{File.basename(project_filepath)} updated"
33
+ else
34
+ puts "All files already added"
20
35
  end
21
- else
22
- write_files(formatters)
23
36
  end
24
37
  end
25
38
 
@@ -35,6 +48,7 @@ module Ovaltine
35
48
  puts " * #{File.basename(path)}"
36
49
  end
37
50
  puts "\n#{files.size} files generated"
51
+ files
38
52
  end
39
53
 
40
54
  def self.prompt title, default_answer
@@ -48,4 +62,12 @@ module Ovaltine
48
62
  answer.downcase == 'y'
49
63
  end
50
64
  end
65
+
66
+ def self.require_formatter(language='objc')
67
+ case language
68
+ when 'objc'
69
+ require 'ovaltine/objc/storyboard_formatter'
70
+ require 'ovaltine/objc/storyboard_templates'
71
+ end
72
+ end
51
73
  end
@@ -1,7 +1,8 @@
1
1
  $:.unshift File.expand_path('../../lib', __FILE__)
2
2
 
3
3
  require 'bacon'
4
- require 'ovaltine'
4
+ require 'ovaltine/storyboard'
5
+ require 'ovaltine/objc/storyboard_formatter'
5
6
 
6
7
  describe 'StoryboardFormatter' do
7
8
 
@@ -0,0 +1,57 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ (see GPL file), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict
21
+ with standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
45
+ files under the ./missing directory. See each file for the copying
46
+ condition.
47
+
48
+ 5. The scripts and library files supplied as input to or produced as
49
+ output from the software do not automatically fall under the
50
+ copyright of the software, but belong to whomever generated them,
51
+ and may be sold commercially, and may be aggregated with this
52
+ software.
53
+
54
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
55
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57
+ PURPOSE.