xcselect 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  .bundle
2
2
  Gemfile.lock
3
+ pkg
data/README.md CHANGED
@@ -48,7 +48,10 @@ Open documents folder for last built app
48
48
 
49
49
  $ xcsim -d
50
50
 
51
+ Open Caches folder for last built app
51
52
 
53
+ $ xcsim -c
54
+
52
55
  Add -p before any of these and xcsim will print the path.
53
56
 
54
57
  If there will be only 1 item to select from the menu will not be displayed and that item will be implicitly selected.
data/bin/xcselect CHANGED
@@ -4,26 +4,7 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
4
 
5
5
  require 'xcselect'
6
6
  require 'optparse'
7
-
8
- class String
9
- def red; colorize(self, "\e[1m\e[31m"); end
10
- def dark_red; colorize(self, "\e\[31m"); end
11
- def green; colorize(self, "\e[1m\e[32m"); end
12
- def dark_green; colorize(self, "\e[32m"); end
13
- def yellow; colorize(self, "\e[1m\e[33m"); end
14
- def dark_yellow; colorize(self, "\e[33m"); end
15
- def blue; colorize(self, "\e[1m\e[34m"); end
16
- def dark_blue; colorize(self, "\e[34m"); end
17
- def pur; colorize(self, "\e[1m\e[35m"); end
18
- def dark_pur; colorize(self, "\e[35m"); end
19
- def colorize(text, color_code)
20
- (STDIN.tty?) ? "#{color_code}#{text}\e[0m" : text
21
- end
22
-
23
- def numeric?
24
- true if Float(self) rescue false
25
- end
26
- end
7
+ require "xcselect/string_colors.rb"
27
8
 
28
9
  include Xcselect
29
10
 
data/bin/xcsim CHANGED
@@ -5,35 +5,58 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
5
5
  require 'xcselect'
6
6
  require "fileutils"
7
7
  require "optparse"
8
+ require "xcselect/string_colors.rb"
8
9
 
9
10
  include Xcselect
11
+
12
+ class XcSelectInvalidSelectionException < Exception; end
13
+
14
+
10
15
  class Main
11
16
  attr_reader :exit_code
17
+ attr_accessor :command
18
+ attr_reader :optparse
12
19
  def initialize
13
20
  @options = default_options
14
21
  @exit_code = 0
15
- optparse = OptionParser.new do |opts|
16
- opts.on('-h', '--help', "Display this !!") { puts opts; exit }
17
- opts.on('-v', '--version', "Print version info") { puts "xcselect-" + VERSION; exit; }
18
-
22
+ @optparse = OptionParser.new do |opts|
19
23
  opts.on('-p', '--print', "print the path instead of opening it") { @options[:print] = true }
20
- opts.on('-c', '--cd', "cd into the directory (spawns new shell, type `exit` to return) ") { @options[:print] = false; @options[:cd] = true }
24
+ opts.on('-t', '--touch-app' , "touch app so it becomes latest") { @options[:touch_app] = true }
25
+ opts.on('--cd', "cd into the directory (spawns new shell, type `exit` to return) ") { @options[:print] = false; @options[:cd] = true }
21
26
 
22
- opts.on('-a', '--apps' , "Show list of apps") { show_apps(); exit }
23
- opts.on('-d', '--latest-documents' , "Reveal last built app's documents folder") { show_latest_docs() ;exit}
24
- opts.on('-n', '--latest-newsstand' , "Show list of newsstand issues for last built app") { show_latest_newsstand(); exit }
27
+ # Commands
28
+ opts.on('-h', '--help', "Display this !!") { self.command = :show_help }
29
+ opts.on('-v', '--version', "Print version info") { self.command = :show_version }
30
+ opts.on('-d', '--latest-documents' , "Reveal last built app's documents folder") { self.command = :show_latest_docs}
31
+ opts.on('-n', '--latest-newsstand' , "Show list of newsstand issues for last built app") { self.command = :show_latest_newsstand }
32
+ opts.on('-c', '--latest-cache' , "Reveal last built app's cache folder") { self.command = :show_latest_cache }
33
+ opts.on('-a', '--apps' , "Show list of apps") { self.command = :show_apps ;}
25
34
  end
26
35
  begin
27
36
  optparse.parse!
37
+ run
28
38
  rescue OptionParser::InvalidOption => e
29
39
  puts "Invalid Option"
30
40
  puts optparse
31
41
  exit 2
42
+ rescue XcSelectInvalidSelectionException => e
43
+ puts "xcsim: #{e}"
32
44
  end
33
45
  end
34
46
 
47
+ def command=(c)
48
+ return @command = c if @command.nil?
49
+ @exit_code = 4
50
+ raise XcSelectInvalidSelectionException, "Please use only one command"
51
+ end
52
+
53
+ def run
54
+ send(command || :show_apps)
55
+ end
56
+
57
+
35
58
  def default_options
36
- {:print => false}
59
+ {:print => false, :touch_app => false}
37
60
  end
38
61
 
39
62
  def open_path p
@@ -45,17 +68,15 @@ class Main
45
68
  elsif @options[:print]
46
69
  puts p
47
70
  else
48
- `open -R "#{p}"`
71
+ `open -R "#{p}"`
49
72
  end
50
73
  end
51
74
 
75
+
52
76
  def select_menu title, selections
53
- i = 0
54
- puts title
55
- puts ""
56
- selections.each do |opt|
57
- i += 1
58
- puts " [#{i}] #{opt}"
77
+ puts "#{title}\n\n"
78
+ selections.each_with_index do |opt,i|
79
+ puts " [#{i+1}] #{opt}"
59
80
  end
60
81
  print "\nSelection: "
61
82
  begin
@@ -63,8 +84,8 @@ class Main
63
84
  input = STDIN.gets
64
85
  input = input.to_i
65
86
  if input.zero? or input > selections.size
66
- puts "Invalid Selection"
67
87
  @exit_code = 1
88
+ raise XcSelectInvalidSelectionException, "Invalid Selection"
68
89
  else
69
90
  yield input - 1
70
91
  end
@@ -80,24 +101,32 @@ class Main
80
101
  def show_latest_newsstand
81
102
  latest_app = XcApp.last_built_newsstand_app
82
103
  ns_issues = latest_app.newsstand_objects
83
- issue_paths = latest_app.newsstand_issue_paths
84
104
  issue_names = ns_issues.keys
85
105
  if issue_names.size == 1
86
106
  puts "opening only issue #{issue_names.last}" unless @options[:print]
87
- open_path ns_issues.last[issue_names.last]
107
+ open_path ns_issues.values.last.content_path
88
108
  return
89
109
  end
90
110
  select_menu("Select issue in #{latest_app} to open:", issue_names) {|i|
91
- open_path ns_issues.values[i]
111
+ open_path ns_issues.values[i].content_path
92
112
  }
93
113
 
94
114
  end
95
115
 
116
+ def show_latest_cache
117
+ app = XcApp.last_built_app
118
+ open_path app.cache_path
119
+ end
120
+
96
121
  def show_latest_docs
97
122
  app = XcApp.last_built_app
98
123
  open_path app.documents_path
99
124
  end
100
125
 
126
+ def touch_app app
127
+ FileUtils.touch app.path
128
+ end
129
+
101
130
  def show_apps
102
131
  apps = XcApp.all_apps.sort
103
132
  return @exit_code = 1 if apps.size == 0
@@ -105,9 +134,37 @@ class Main
105
134
  puts "opening only app #{apps}" unless @options[:print]
106
135
  open_path issue_paths.last
107
136
  end
108
- select_menu("Select an app to open:", apps.map(&:to_s)) do |selected_index|
109
- open_path(apps[selected_index].base_dir)
137
+
138
+ last_app = XcApp.sort_by_touch_time(apps).last
139
+ last_newsstand_app = apps.select(&:newsstand?).last
140
+ same_last_app = last_app.equal? last_newsstand_app
141
+
142
+ options = apps.map do |a|
143
+ s = a.to_s
144
+ if a.equal? last_app
145
+ s += " " + (same_last_app ? "[latest]".green : "[latest]".blue)
146
+ elsif a.equal? last_newsstand_app
147
+ s += "[latest-ns]".yellow
148
+ end
149
+ s
110
150
  end
151
+
152
+ select_menu("Select an app to open:", options) do |selected_index|
153
+ selected_app = apps[selected_index]
154
+ if @options[:touch_app]
155
+ touch_app selected_app
156
+ else
157
+ open_path(selected_app.base_dir)
158
+ end
159
+ end
160
+ end
161
+
162
+ def show_help
163
+ puts @optparse
164
+ end
165
+
166
+ def show_version
167
+ puts "xcselect-" + VERSION
111
168
  end
112
169
  end
113
170
 
@@ -0,0 +1,55 @@
1
+
2
+ module Xcselect
3
+ require "plist"
4
+
5
+ # Seams apple stores there internal dates with the base of 2001-01-01
6
+ NSTimeIntervalSince1970 = 978307200.0
7
+
8
+ class NKIssue
9
+ include Comparable
10
+ attr_accessor :name
11
+ attr_accessor :uuid
12
+ attr_accessor :date
13
+ attr_accessor :content_path
14
+
15
+ def self.find_class_key hash
16
+ hash['$objects'].index(hash['$objects'].select{|o| o['$classname'] == "NKIssue"}.first)
17
+ end
18
+
19
+ def self.parse file_name
20
+ ns_plist = Plist::parse_xml(read_bin_plist_to_xml(file_name))
21
+ # this is the integer that we will use to filter all archived nkissue objects
22
+ nk_issue_key = find_class_key(ns_plist)
23
+
24
+ # filter just the nkissue hashes
25
+ object_array = ns_plist['$objects']
26
+ obj_key_hashs = object_array.select{|o| o.class == Hash && o['$class'] && nk_issue_key == o['$class']['CF$UID'] }
27
+
28
+ issues = {}
29
+ obj_key_hashs.each do |nskey|
30
+ issue = NKIssue.new
31
+ issue.name = object_array[nskey['name']['CF$UID']]
32
+ issue.uuid = object_array[nskey['directory']['CF$UID']]
33
+ issue.date = self.archive_time_to_time(object_array[nskey['date']['CF$UID']]['NS.time'])
34
+ issues[issue.name] = issue # unless name.nil?
35
+ end
36
+ return issues
37
+ end
38
+
39
+ def to_s
40
+ "<NKIssue:#{name}:#{date} #{uuid}>"
41
+ end
42
+
43
+ # convert a date offset from 2001 to epoch
44
+ def self.archive_time_to_time t
45
+ Time.at(t + NSTimeIntervalSince1970)
46
+ end
47
+
48
+ def self.read_bin_plist_to_xml plist_path
49
+ `plutil -convert xml1 -o - '#{plist_path}'`
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+
@@ -0,0 +1,19 @@
1
+ class String
2
+ def red; colorize(self, "\e[1m\e[31m"); end
3
+ def dark_red; colorize(self, "\e\[31m"); end
4
+ def green; colorize(self, "\e[1m\e[32m"); end
5
+ def dark_green; colorize(self, "\e[32m"); end
6
+ def yellow; colorize(self, "\e[1m\e[33m"); end
7
+ def dark_yellow; colorize(self, "\e[33m"); end
8
+ def blue; colorize(self, "\e[1m\e[34m"); end
9
+ def dark_blue; colorize(self, "\e[34m"); end
10
+ def pur; colorize(self, "\e[1m\e[35m"); end
11
+ def dark_pur; colorize(self, "\e[35m"); end
12
+ def colorize(text, color_code)
13
+ (STDIN.tty?) ? "#{color_code}#{text}\e[0m" : text
14
+ end
15
+
16
+ def numeric?
17
+ true if Float(self) rescue false
18
+ end
19
+ end
@@ -1,3 +1,3 @@
1
1
  module Xcselect
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.4"
3
3
  end
@@ -3,15 +3,16 @@ module Xcselect
3
3
  require 'pathname'
4
4
  require 'json'
5
5
  require "plist"
6
+ require 'xcselect/nkissue'
6
7
 
7
8
  class XcApp
8
9
  include Comparable
9
10
  attr_reader :path
10
- attr_reader :plist
11
+ attr_reader :info_plist
11
12
 
12
13
  def initialize(path)
13
14
  @path = path
14
- @plist = JSON.parse read_plist(plist_path)
15
+ @info_plist = JSON.parse read_plist(plist_path)
15
16
  end
16
17
 
17
18
  def to_s
@@ -28,7 +29,7 @@ module Xcselect
28
29
  end
29
30
 
30
31
  def [](k)
31
- @plist[k]
32
+ @info_plist[k]
32
33
  end
33
34
 
34
35
  def base_dir
@@ -59,6 +60,10 @@ module Xcselect
59
60
  "#{base_dir}/Documents"
60
61
  end
61
62
 
63
+ def cache_path
64
+ "#{base_dir}/Library/Caches"
65
+ end
66
+
62
67
  def oomph_app?
63
68
  File.exists? "#{path}/Oomph.plist"
64
69
  end
@@ -67,36 +72,26 @@ module Xcselect
67
72
  self['UINewsstandApp'] || false
68
73
  end
69
74
 
75
+ # Returns a hash of NKIssues in the form {"issue_name" => path }
70
76
  def newsstand_objects
71
- issues = {}
77
+ issues = NKIssue.parse "#{base_dir}/Library/Application Support/com.apple.newsstand-library.plist"
78
+
72
79
  return issues unless newsstand?
73
- # this is an NSKeyedArchiver plist
74
- ns_plist = Plist::parse_xml(read_bin_plist_to_xml("#{base_dir}/Library/Application Support/com.apple.newsstand-library.plist"))
75
-
76
- # this is the integer that we will use to filter all archived nkissue objects
77
- nk_issue_key = ns_plist['$objects'].index(ns_plist['$objects'].select{|o| o['$classname'] == "NKIssue"}.last)
78
-
79
- # filter just the nkissue hashes
80
- obj_key_hashs = ns_plist['$objects'].select{|o| o.class == Hash && o['$class'] && nk_issue_key == o['$class']['CF$UID'] }
81
- object_array = ns_plist['$objects']
82
-
83
- # load these paths as our apps have 1 folder inside the newsstand folders
84
- paths = newsstand_issue_paths if oomph_app?
85
-
86
- obj_key_hashs.each do |nskey|
87
- name = object_array[nskey['name']['CF$UID']]
88
- uuid = object_array[nskey['directory']['CF$UID']]
89
- next if name.nil?
90
- issues[name] = "#{newsstand_path}/#{uuid}"
91
- issues[name] = paths.select{|p| p[uuid] }.last if oomph_app? # specially for me :)
80
+ paths = newsstand_issue_paths if oomph_app?
81
+ issues.values.each do |issue|
82
+ issue.content_path = "#{newsstand_path}/#{issue.uuid}"
83
+ issue.content_path = paths.select{|p| p[issue.uuid] }.last if oomph_app?
92
84
  end
85
+
93
86
  return issues
94
87
  end
95
88
 
89
+ # path to the app's root newsstand folder
96
90
  def newsstand_path
97
91
  "#{base_dir}/Library/Caches/Newsstand"
98
92
  end
99
93
 
94
+ # all directories in newsstand folder
100
95
  def newsstand_issue_paths
101
96
  #TODO: make this read the newsstand db and return a hash of names/paths
102
97
  if oomph_app?
@@ -105,19 +100,24 @@ module Xcselect
105
100
  Dir["#{newsstand_path}/*-*"]
106
101
  end
107
102
  end
108
-
103
+
109
104
  def last_build_time
110
105
  File.mtime path
111
106
  end
107
+
108
+ # Class methods
112
109
 
110
+ # the iPhone Simulator support folder
113
111
  def self.app_support_folder
114
112
  File.expand_path("~/Library/Application Support/iPhone Simulator/")
115
113
  end
116
114
 
115
+ # all applications for all simulator versions, unsorted
117
116
  def self.all_apps
118
117
  Dir["#{app_support_folder}/**/*.app"].map{|a| XcApp.new a }
119
118
  end
120
-
119
+
120
+ # every newsstand application
121
121
  def self.all_newsstand_apps
122
122
  self.all_apps.select(&:newsstand?)
123
123
  end
@@ -126,8 +126,12 @@ module Xcselect
126
126
  all_newsstand_apps.sort_by!{|e| e.last_build_time }.last
127
127
  end
128
128
 
129
+ def self.sort_by_touch_time array
130
+ array.sort_by{|e| e.last_build_time }
131
+ end
132
+
129
133
  def self.last_built_app
130
- XcApp.all_apps.sort_by!{|e| e.last_build_time }.last
134
+ XcApp.sort_by_touch_time(all_apps).last
131
135
  end
132
136
 
133
137
  end
@@ -33,7 +33,7 @@ class Xcode
33
33
  end
34
34
 
35
35
  def self.find_new_xcodes
36
- # Xcode in now in a single application, look for that and use that as a candidate
36
+ # Xcode is now in a single application, look for that and use that as a candidate
37
37
  newXcodes = `mdfind 'kMDItemCFBundleIdentifier = com.apple.dt.Xcode'`.chomp.split
38
38
  newXcodes = newXcodes.select do |x|
39
39
  File.exists? x + "/Contents/Developer/usr/bin/xcodebuild"
data/lib/xcselect.rb CHANGED
@@ -5,5 +5,6 @@ require "xcselect/xcode"
5
5
  require "xcselect/xcapp"
6
6
  require "xcselect/version"
7
7
  require "xcselect/dir_extension"
8
+ require "xcselect/nkissue"
8
9
 
9
10
  end
@@ -0,0 +1,407 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>$archiver</key>
6
+ <string>NSKeyedArchiver</string>
7
+ <key>$objects</key>
8
+ <array>
9
+ <string>$null</string>
10
+ <dict>
11
+ <key>$class</key>
12
+ <dict>
13
+ <key>CF$UID</key>
14
+ <integer>36</integer>
15
+ </dict>
16
+ <key>NS.keys</key>
17
+ <array>
18
+ <dict>
19
+ <key>CF$UID</key>
20
+ <integer>2</integer>
21
+ </dict>
22
+ </array>
23
+ <key>NS.objects</key>
24
+ <array>
25
+ <dict>
26
+ <key>CF$UID</key>
27
+ <integer>3</integer>
28
+ </dict>
29
+ </array>
30
+ </dict>
31
+ <string>issues</string>
32
+ <dict>
33
+ <key>$class</key>
34
+ <dict>
35
+ <key>CF$UID</key>
36
+ <integer>10</integer>
37
+ </dict>
38
+ <key>NS.objects</key>
39
+ <array>
40
+ <dict>
41
+ <key>CF$UID</key>
42
+ <integer>4</integer>
43
+ </dict>
44
+ <dict>
45
+ <key>CF$UID</key>
46
+ <integer>12</integer>
47
+ </dict>
48
+ <dict>
49
+ <key>CF$UID</key>
50
+ <integer>16</integer>
51
+ </dict>
52
+ <dict>
53
+ <key>CF$UID</key>
54
+ <integer>20</integer>
55
+ </dict>
56
+ <dict>
57
+ <key>CF$UID</key>
58
+ <integer>24</integer>
59
+ </dict>
60
+ <dict>
61
+ <key>CF$UID</key>
62
+ <integer>28</integer>
63
+ </dict>
64
+ <dict>
65
+ <key>CF$UID</key>
66
+ <integer>32</integer>
67
+ </dict>
68
+ </array>
69
+ </dict>
70
+ <dict>
71
+ <key>$class</key>
72
+ <dict>
73
+ <key>CF$UID</key>
74
+ <integer>11</integer>
75
+ </dict>
76
+ <key>assets</key>
77
+ <dict>
78
+ <key>CF$UID</key>
79
+ <integer>9</integer>
80
+ </dict>
81
+ <key>date</key>
82
+ <dict>
83
+ <key>CF$UID</key>
84
+ <integer>6</integer>
85
+ </dict>
86
+ <key>directory</key>
87
+ <dict>
88
+ <key>CF$UID</key>
89
+ <integer>8</integer>
90
+ </dict>
91
+ <key>foundContent</key>
92
+ <false/>
93
+ <key>name</key>
94
+ <dict>
95
+ <key>CF$UID</key>
96
+ <integer>5</integer>
97
+ </dict>
98
+ </dict>
99
+ <string>Lion</string>
100
+ <dict>
101
+ <key>$class</key>
102
+ <dict>
103
+ <key>CF$UID</key>
104
+ <integer>7</integer>
105
+ </dict>
106
+ <key>NS.time</key>
107
+ <real>332776800.000000</real>
108
+ </dict>
109
+ <dict>
110
+ <key>$classes</key>
111
+ <array>
112
+ <string>NSDate</string>
113
+ <string>NSObject</string>
114
+ </array>
115
+ <key>$classname</key>
116
+ <string>NSDate</string>
117
+ </dict>
118
+ <string>93EF18D7-BED2-4770-AE8B-46A5C406D7D3</string>
119
+ <dict>
120
+ <key>$class</key>
121
+ <dict>
122
+ <key>CF$UID</key>
123
+ <integer>10</integer>
124
+ </dict>
125
+ <key>NS.objects</key>
126
+ <array/>
127
+ </dict>
128
+ <dict>
129
+ <key>$classes</key>
130
+ <array>
131
+ <string>NSArray</string>
132
+ <string>NSObject</string>
133
+ </array>
134
+ <key>$classname</key>
135
+ <string>NSArray</string>
136
+ </dict>
137
+ <dict>
138
+ <key>$classes</key>
139
+ <array>
140
+ <string>NKIssue</string>
141
+ <string>NSObject</string>
142
+ </array>
143
+ <key>$classname</key>
144
+ <string>NKIssue</string>
145
+ </dict>
146
+ <dict>
147
+ <key>$class</key>
148
+ <dict>
149
+ <key>CF$UID</key>
150
+ <integer>11</integer>
151
+ </dict>
152
+ <key>assets</key>
153
+ <dict>
154
+ <key>CF$UID</key>
155
+ <integer>9</integer>
156
+ </dict>
157
+ <key>date</key>
158
+ <dict>
159
+ <key>CF$UID</key>
160
+ <integer>14</integer>
161
+ </dict>
162
+ <key>directory</key>
163
+ <dict>
164
+ <key>CF$UID</key>
165
+ <integer>15</integer>
166
+ </dict>
167
+ <key>foundContent</key>
168
+ <false/>
169
+ <key>name</key>
170
+ <dict>
171
+ <key>CF$UID</key>
172
+ <integer>13</integer>
173
+ </dict>
174
+ </dict>
175
+ <string>Mountain Lion</string>
176
+ <dict>
177
+ <key>$class</key>
178
+ <dict>
179
+ <key>CF$UID</key>
180
+ <integer>7</integer>
181
+ </dict>
182
+ <key>NS.time</key>
183
+ <real>364831200.000000</real>
184
+ </dict>
185
+ <string>8BA10DB9-0442-4CE1-8D06-10E0B5939DA7</string>
186
+ <dict>
187
+ <key>$class</key>
188
+ <dict>
189
+ <key>CF$UID</key>
190
+ <integer>11</integer>
191
+ </dict>
192
+ <key>assets</key>
193
+ <dict>
194
+ <key>CF$UID</key>
195
+ <integer>9</integer>
196
+ </dict>
197
+ <key>date</key>
198
+ <dict>
199
+ <key>CF$UID</key>
200
+ <integer>18</integer>
201
+ </dict>
202
+ <key>directory</key>
203
+ <dict>
204
+ <key>CF$UID</key>
205
+ <integer>19</integer>
206
+ </dict>
207
+ <key>foundContent</key>
208
+ <false/>
209
+ <key>name</key>
210
+ <dict>
211
+ <key>CF$UID</key>
212
+ <integer>17</integer>
213
+ </dict>
214
+ </dict>
215
+ <string>Snow Leopard</string>
216
+ <dict>
217
+ <key>$class</key>
218
+ <dict>
219
+ <key>CF$UID</key>
220
+ <integer>7</integer>
221
+ </dict>
222
+ <key>NS.time</key>
223
+ <real>273074400.000000</real>
224
+ </dict>
225
+ <string>846B96F1-E081-4120-A9E9-314ED21AB22C</string>
226
+ <dict>
227
+ <key>$class</key>
228
+ <dict>
229
+ <key>CF$UID</key>
230
+ <integer>11</integer>
231
+ </dict>
232
+ <key>assets</key>
233
+ <dict>
234
+ <key>CF$UID</key>
235
+ <integer>9</integer>
236
+ </dict>
237
+ <key>date</key>
238
+ <dict>
239
+ <key>CF$UID</key>
240
+ <integer>22</integer>
241
+ </dict>
242
+ <key>directory</key>
243
+ <dict>
244
+ <key>CF$UID</key>
245
+ <integer>23</integer>
246
+ </dict>
247
+ <key>foundContent</key>
248
+ <false/>
249
+ <key>name</key>
250
+ <dict>
251
+ <key>CF$UID</key>
252
+ <integer>21</integer>
253
+ </dict>
254
+ </dict>
255
+ <string>Leopard</string>
256
+ <dict>
257
+ <key>$class</key>
258
+ <dict>
259
+ <key>CF$UID</key>
260
+ <integer>7</integer>
261
+ </dict>
262
+ <key>NS.time</key>
263
+ <real>215013600.000000</real>
264
+ </dict>
265
+ <string>1874F72E-13FE-4B68-80D7-FB377AE5ACDA</string>
266
+ <dict>
267
+ <key>$class</key>
268
+ <dict>
269
+ <key>CF$UID</key>
270
+ <integer>11</integer>
271
+ </dict>
272
+ <key>assets</key>
273
+ <dict>
274
+ <key>CF$UID</key>
275
+ <integer>9</integer>
276
+ </dict>
277
+ <key>date</key>
278
+ <dict>
279
+ <key>CF$UID</key>
280
+ <integer>26</integer>
281
+ </dict>
282
+ <key>directory</key>
283
+ <dict>
284
+ <key>CF$UID</key>
285
+ <integer>27</integer>
286
+ </dict>
287
+ <key>foundContent</key>
288
+ <false/>
289
+ <key>name</key>
290
+ <dict>
291
+ <key>CF$UID</key>
292
+ <integer>25</integer>
293
+ </dict>
294
+ </dict>
295
+ <string>Tiger</string>
296
+ <dict>
297
+ <key>$class</key>
298
+ <dict>
299
+ <key>CF$UID</key>
300
+ <integer>7</integer>
301
+ </dict>
302
+ <key>NS.time</key>
303
+ <real>136389600.000000</real>
304
+ </dict>
305
+ <string>E1131C38-2719-490D-8D67-EFB1B6D08252</string>
306
+ <dict>
307
+ <key>$class</key>
308
+ <dict>
309
+ <key>CF$UID</key>
310
+ <integer>11</integer>
311
+ </dict>
312
+ <key>assets</key>
313
+ <dict>
314
+ <key>CF$UID</key>
315
+ <integer>9</integer>
316
+ </dict>
317
+ <key>date</key>
318
+ <dict>
319
+ <key>CF$UID</key>
320
+ <integer>30</integer>
321
+ </dict>
322
+ <key>directory</key>
323
+ <dict>
324
+ <key>CF$UID</key>
325
+ <integer>31</integer>
326
+ </dict>
327
+ <key>foundContent</key>
328
+ <false/>
329
+ <key>name</key>
330
+ <dict>
331
+ <key>CF$UID</key>
332
+ <integer>29</integer>
333
+ </dict>
334
+ </dict>
335
+ <string>Panther</string>
336
+ <dict>
337
+ <key>$class</key>
338
+ <dict>
339
+ <key>CF$UID</key>
340
+ <integer>7</integer>
341
+ </dict>
342
+ <key>NS.time</key>
343
+ <real>88610400.000000</real>
344
+ </dict>
345
+ <string>7C6268CD-B443-4417-96FC-B1CCFE5CA552</string>
346
+ <dict>
347
+ <key>$class</key>
348
+ <dict>
349
+ <key>CF$UID</key>
350
+ <integer>11</integer>
351
+ </dict>
352
+ <key>assets</key>
353
+ <dict>
354
+ <key>CF$UID</key>
355
+ <integer>9</integer>
356
+ </dict>
357
+ <key>date</key>
358
+ <dict>
359
+ <key>CF$UID</key>
360
+ <integer>34</integer>
361
+ </dict>
362
+ <key>directory</key>
363
+ <dict>
364
+ <key>CF$UID</key>
365
+ <integer>35</integer>
366
+ </dict>
367
+ <key>foundContent</key>
368
+ <false/>
369
+ <key>name</key>
370
+ <dict>
371
+ <key>CF$UID</key>
372
+ <integer>33</integer>
373
+ </dict>
374
+ </dict>
375
+ <string>Jaguar</string>
376
+ <dict>
377
+ <key>$class</key>
378
+ <dict>
379
+ <key>CF$UID</key>
380
+ <integer>7</integer>
381
+ </dict>
382
+ <key>NS.time</key>
383
+ <real>42300000.000000</real>
384
+ </dict>
385
+ <string>A98F7CDC-BE07-4C7D-80F2-F58E14D00CA9</string>
386
+ <dict>
387
+ <key>$classes</key>
388
+ <array>
389
+ <string>NSDictionary</string>
390
+ <string>NSObject</string>
391
+ </array>
392
+ <key>$classname</key>
393
+ <string>NSDictionary</string>
394
+ </dict>
395
+ </array>
396
+ <key>$top</key>
397
+ <dict>
398
+ <key>root</key>
399
+ <dict>
400
+ <key>CF$UID</key>
401
+ <integer>1</integer>
402
+ </dict>
403
+ </dict>
404
+ <key>$version</key>
405
+ <integer>100000</integer>
406
+ </dict>
407
+ </plist>
@@ -0,0 +1,43 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
2
+
3
+ require "xcselect"
4
+ require "test/unit"
5
+ require "time"
6
+
7
+ include Xcselect
8
+
9
+
10
+ class NKIssueTest < Test::Unit::TestCase
11
+ attr_accessor :issues
12
+ def setup
13
+ @issues = NKIssue.parse "big_cats.plist"
14
+ end
15
+
16
+
17
+ def test_parser
18
+
19
+ versions = {"Panther" => "October 24, 2003",
20
+ "Tiger" => "April 29, 2005",
21
+ "Leopard" => "October 26, 2007",
22
+ "Snow Leopard" => "August 28, 2009",
23
+ "Lion" => "July 20, 2011",
24
+ "Mountain Lion" => "July 25, 2012",
25
+ "Jaguar" => "May 6, 2002" }
26
+ versions.each_key do |k|
27
+ nkissue = issues[k]
28
+ release_date = Time.strptime(versions[k], "%b %d, %Y")
29
+
30
+ # test correct date
31
+ assert_equal(nkissue.date, release_date)
32
+
33
+ # test uuid is set
34
+ assert(!nkissue.uuid.size.zero?)
35
+
36
+ assert_equal(7, issues.size)
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+
data/xcselect.gemspec CHANGED
@@ -7,9 +7,9 @@ Gem::Specification.new do |s|
7
7
  s.version = Xcselect::VERSION
8
8
  s.authors = ["Kim Hunter"]
9
9
  s.email = ["bigkm1@gmail.com"]
10
- s.homepage = ""
10
+ s.homepage = "https://github.com/bigkm/xcselect"
11
11
  s.summary = %q{xcselect - Xcode Select}
12
- s.description = %q{A more user friendly interface to the xcode-select command showing more info}
12
+ s.description = %q{A more user friendly interface to the xcode-select command showing more info, xcsim - access the simulator application folders quickly}
13
13
 
14
14
  s.rubyforge_project = "xcselect"
15
15
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xcselect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,10 +9,10 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-02 00:00:00.000000000 Z
12
+ date: 2012-08-05 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A more user friendly interface to the xcode-select command showing more
15
- info
15
+ info, xcsim - access the simulator application folders quickly
16
16
  email:
17
17
  - bigkm1@gmail.com
18
18
  executables:
@@ -29,20 +29,15 @@ files:
29
29
  - bin/xcsim
30
30
  - lib/xcselect.rb
31
31
  - lib/xcselect/dir_extension.rb
32
+ - lib/xcselect/nkissue.rb
33
+ - lib/xcselect/string_colors.rb
32
34
  - lib/xcselect/version.rb
33
35
  - lib/xcselect/xcapp.rb
34
36
  - lib/xcselect/xcode.rb
35
- - pkg/xcselect-0.0.1.gem
36
- - pkg/xcselect-0.0.10.gem
37
- - pkg/xcselect-0.0.11.gem
38
- - pkg/xcselect-0.0.3.gem
39
- - pkg/xcselect-0.0.4.gem
40
- - pkg/xcselect-0.0.5.gem
41
- - pkg/xcselect-0.0.6.gem
42
- - pkg/xcselect-0.0.7.gem
43
- - pkg/xcselect-0.0.9.gem
37
+ - tests/big_cats.plist
38
+ - tests/test_nkissue.rb
44
39
  - xcselect.gemspec
45
- homepage: ''
40
+ homepage: https://github.com/bigkm/xcselect
46
41
  licenses: []
47
42
  post_install_message:
48
43
  rdoc_options: []
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file