wycats-textmate 0.9.2 → 0.9.6
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.
- data/Rakefile +1 -1
- data/bin/textmate +108 -62
- metadata +7 -5
data/Rakefile
CHANGED
data/bin/textmate
CHANGED
@@ -5,17 +5,18 @@ require "rubygems"
|
|
5
5
|
require "thor"
|
6
6
|
require "open-uri"
|
7
7
|
require "yaml"
|
8
|
+
require "cgi"
|
8
9
|
|
9
10
|
class TextmateInstaller < Thor
|
10
|
-
|
11
|
+
|
11
12
|
# CHANGED: renamed list to remote. Could there be a better name?
|
12
|
-
desc "
|
13
|
-
def
|
13
|
+
desc "search [SEARCH]", "Lists all the matching remote bundles"
|
14
|
+
def search(search_term = "")
|
14
15
|
search_term = Regexp.new(".*#{search_term}.*", "i")
|
15
|
-
|
16
|
-
|
16
|
+
|
17
|
+
REMOTE_LOCATIONS.each do |name,location|
|
17
18
|
puts "\n" << name.to_s << " Remote Bundles\n" << name.to_s.gsub(/./,'-') << '---------------'
|
18
|
-
|
19
|
+
|
19
20
|
results = case location[:scm]
|
20
21
|
when :svn
|
21
22
|
%x[svn list #{e_sh location[:url]}].map {|x| x.split(".")[0]}.select {|x| x =~ search_term}.join("\n")
|
@@ -26,50 +27,53 @@ class TextmateInstaller < Thor
|
|
26
27
|
"%s (by %s)" %
|
27
28
|
[
|
28
29
|
normalize_github_repo_name(result['name']).split('.').first,
|
29
|
-
result['
|
30
|
+
result['username']
|
30
31
|
]
|
31
32
|
}
|
32
33
|
end
|
33
|
-
|
34
|
+
|
34
35
|
puts results
|
35
36
|
end
|
36
37
|
end
|
37
|
-
|
38
|
+
|
38
39
|
desc "list [SEARCH]", "lists all the bundles installed locally"
|
39
40
|
def list(search_term = "")
|
40
41
|
search_term = Regexp.new(".*#{search_term}.*", "i")
|
41
|
-
|
42
|
+
|
42
43
|
local_bundle_paths.each do |name,bundles_path|
|
43
44
|
puts "\n" << name.to_s << " Bundles\n" << name.to_s.gsub(/./,'-') << '--------'
|
44
45
|
puts Dir["#{e_sh bundles_path}/*.tmbundle"].map {|x| x.split("/").last.split(".").first}.
|
45
46
|
select {|x| x =~ search_term}.join("\n")
|
46
47
|
end
|
47
48
|
end
|
48
|
-
|
49
|
-
desc "install NAME
|
50
|
-
|
49
|
+
|
50
|
+
desc "install NAME", "Install a bundle. Source must be one of trunk, review, or github. \n" \
|
51
|
+
"If multiple gems with the same name exist, you will be prompted to \n" \
|
52
|
+
"choose from the available list."
|
53
|
+
method_option :source
|
54
|
+
def install(bundle_name)
|
51
55
|
FileUtils.mkdir_p install_bundles_path
|
52
56
|
puts "Checking out #{bundle_name}..."
|
53
|
-
|
57
|
+
|
54
58
|
# CHANGED: It's faster to just try and fail for each repo than to search them all first
|
55
59
|
installed=false
|
56
|
-
|
57
|
-
next unless
|
58
|
-
|
60
|
+
REMOTE_LOCATIONS.each do |remote_name,location|
|
61
|
+
next unless remote_bundle(options["source"]) == location if options.key?("source")
|
62
|
+
|
59
63
|
cmd = case location[:scm]
|
60
64
|
when :git
|
61
65
|
'echo "git remotes not implemented yet"'
|
62
66
|
when :svn
|
63
|
-
%[svn co #{
|
67
|
+
%[svn co "#{location[:url]}/#{url_escape bundle_name}.tmbundle" #{e_sh install_bundles_path}/#{e_sh bundle_name}.tmbundle 2>&1]
|
64
68
|
when :github
|
65
69
|
repos = find_github_bundles(denormalize_github_repo_name(bundle_name))
|
66
|
-
|
70
|
+
|
67
71
|
# Handle possible multiple Repos with the same name
|
68
72
|
case repos.size
|
69
73
|
when 0
|
70
74
|
'echo "Sorry, no such bundle found"'
|
71
75
|
when 1
|
72
|
-
|
76
|
+
git_clone(repos.first["username"], repos.first["name"])
|
73
77
|
else
|
74
78
|
puts "Multiple bundles with that name found. Please choose which one you want to install:"
|
75
79
|
repos.each_with_index {|repo, idx|
|
@@ -77,49 +81,57 @@ class TextmateInstaller < Thor
|
|
77
81
|
[
|
78
82
|
idx + 1,
|
79
83
|
normalize_github_repo_name(repo['name']),
|
80
|
-
repo['
|
84
|
+
repo['username']
|
81
85
|
]
|
82
86
|
}
|
83
87
|
print "Your choice: "
|
84
|
-
|
88
|
+
|
85
89
|
# Since to_i defaults to 0, we have to use Integer
|
86
90
|
choice = Integer(STDIN.gets.chomp) rescue nil
|
87
91
|
until choice && (0...repos.size).include?( choice - 1 ) do
|
88
92
|
print "Sorry, invalid choice. Please enter a valid number or Ctrl+C to stop: "
|
89
93
|
choice = Integer(STDIN.gets.chomp) rescue nil
|
90
94
|
end
|
91
|
-
|
92
|
-
|
95
|
+
|
96
|
+
git_clone(repos[choice - 1]["username"], repos[choice - 1]["name"])
|
93
97
|
end
|
94
98
|
end
|
95
|
-
|
99
|
+
|
96
100
|
res = %x{#{cmd}}
|
97
|
-
|
101
|
+
|
98
102
|
puts cmd, res.gsub(/^/,' ')
|
99
|
-
|
103
|
+
|
100
104
|
installed=true and break if res =~ /Checked out revision|Initialized empty Git repository/
|
101
105
|
end
|
102
106
|
abort 'Not Installed' unless installed
|
103
|
-
|
107
|
+
|
104
108
|
reload :verbose => true
|
105
109
|
end
|
106
110
|
|
107
111
|
desc "uninstall NAME", "uninstall a bundle"
|
108
112
|
def uninstall(bundle_name)
|
113
|
+
removed = false
|
114
|
+
|
109
115
|
puts "Removing bundle..."
|
110
|
-
# When moving to the trash, maybe move the bundle into a trash/disabled_bundles subfolder
|
111
|
-
# named as the bundles_path key. Just in case there are multiple versions of
|
116
|
+
# When moving to the trash, maybe move the bundle into a trash/disabled_bundles subfolder
|
117
|
+
# named as the bundles_path key. Just in case there are multiple versions of
|
112
118
|
# the same bundle in multiple bundle paths
|
113
119
|
local_bundle_paths.each do |name,bundles_path|
|
114
120
|
bundle_path = "#{bundles_path}/#{bundle_name}.tmbundle"
|
115
121
|
if File.exist? bundle_path
|
122
|
+
removed = true
|
116
123
|
%x[osascript -e 'tell application "Finder" to move the POSIX file "#{bundle_path}" to trash']
|
117
124
|
end
|
118
125
|
end
|
119
|
-
|
120
|
-
|
126
|
+
|
127
|
+
unless removed
|
128
|
+
say "There is no bundle by that name in the system", :red
|
129
|
+
exit
|
130
|
+
else
|
131
|
+
reload :verbose => true
|
132
|
+
end
|
121
133
|
end
|
122
|
-
|
134
|
+
|
123
135
|
desc "reload", "Reloads TextMate Bundles"
|
124
136
|
method_options :verbose => :boolean
|
125
137
|
def reload(opts = {})
|
@@ -127,18 +139,24 @@ class TextmateInstaller < Thor
|
|
127
139
|
%x[osascript -e 'tell app "TextMate" to reload bundles']
|
128
140
|
puts "Done." if opts[:verbose]
|
129
141
|
end
|
130
|
-
|
142
|
+
|
131
143
|
private
|
132
|
-
|
133
|
-
{ :'Macromates Trunk' => {:scm => :svn, :url => 'http://
|
134
|
-
:'Macromates Review' => {:scm => :svn, :url => 'http://
|
135
|
-
|
144
|
+
REMOTE_LOCATIONS =
|
145
|
+
{ :'Macromates Trunk' => {:scm => :svn, :url => 'http://svn.textmate.org/trunk/Bundles'},
|
146
|
+
:'Macromates Review' => {:scm => :svn, :url => 'http://svn.textmate.org/trunk/Review/Bundles'},
|
147
|
+
|
136
148
|
# :'Bunch of Git Bundles' => {:scm => :git, :url => 'git://NotImplemented'},
|
137
|
-
|
149
|
+
|
138
150
|
:'GitHub' => {:scm => :github, :url => 'http://github.com/search?q=tmbundle'},
|
139
151
|
}
|
152
|
+
|
153
|
+
SHORT_LOCATIONS = {:trunk => :"Macromates Trunk", :review => :"Macromates Review", :github => :"GitHub"}
|
154
|
+
|
155
|
+
def remote_bundle(name)
|
156
|
+
name = name.to_sym
|
157
|
+
REMOTE_LOCATIONS[name] || REMOTE_LOCATIONS[SHORT_LOCATIONS[name]]
|
140
158
|
end
|
141
|
-
|
159
|
+
|
142
160
|
def local_bundle_paths
|
143
161
|
{ :Application => '/Applications/TextMate.app/Contents/SharedSupport/Bundles',
|
144
162
|
:User => "#{ENV["HOME"]}/Library/Application Support/TextMate/Bundles",
|
@@ -147,48 +165,76 @@ class TextmateInstaller < Thor
|
|
147
165
|
:'System Pristine' => '/Library/Application Support/TextMate/Pristine Copy/Bundles',
|
148
166
|
}
|
149
167
|
end
|
150
|
-
|
168
|
+
|
151
169
|
def install_bundles_path
|
152
170
|
local_bundle_paths[:'User Pristine']
|
153
171
|
end
|
154
|
-
|
172
|
+
|
155
173
|
# Copied from http://macromates.com/svn/Bundles/trunk/Support/lib/escape.rb
|
156
174
|
# escape text to make it useable in a shell script as one “word” (string)
|
157
175
|
def e_sh(str)
|
158
176
|
str.to_s.gsub(/(?=[^a-zA-Z0-9_.\/\-\x7F-\xFF\n])/, '\\').gsub(/\n/, "'\n'").sub(/^$/, "''")
|
159
177
|
end
|
160
|
-
|
178
|
+
|
179
|
+
def url_escape(str)
|
180
|
+
chars = ((33...47).to_a + (94...96).to_a + (123...126).to_a).map {|c| c.chr }.join + "\\[\\]\\\\"
|
181
|
+
str = str.to_s.gsub(%r{[#{chars}]}) {|m| CGI.escape(m) }
|
182
|
+
end
|
183
|
+
|
161
184
|
CAPITALIZATION_EXCEPTIONS = %w[tmbundle on]
|
162
185
|
# Convert a GitHub repo name into a "normal" TM bundle name
|
163
186
|
# e.g. ruby-on-rails-tmbundle => Ruby on Rails.tmbundle
|
164
187
|
def normalize_github_repo_name(name)
|
165
|
-
name = name.gsub(
|
188
|
+
name = name.gsub(/[\-\.]/, " ").split.each{|part| part.capitalize! unless CAPITALIZATION_EXCEPTIONS.include? part}.join(" ")
|
166
189
|
name[-9] = ?. if name =~ / tmbundle$/
|
167
190
|
name
|
168
191
|
end
|
169
|
-
|
192
|
+
|
170
193
|
# Does the opposite of normalize_github_repo_name
|
171
194
|
def denormalize_github_repo_name(name)
|
172
|
-
name
|
173
|
-
name
|
195
|
+
name = name.split(' ').each{|part| part.downcase!}.join(' ').gsub(' ', '-')
|
196
|
+
name += ".tmbundle" unless name =~ /.tmbundle$/
|
197
|
+
name
|
174
198
|
end
|
175
|
-
|
199
|
+
|
176
200
|
def find_github_bundles(search_term)
|
177
|
-
|
178
|
-
|
179
|
-
|
201
|
+
# Until GitHub fixes http://support.github.com/discussions/feature-requests/11-api-search-results,
|
202
|
+
# we need to account for multiple pages of results:
|
203
|
+
page = 1
|
204
|
+
repositories = YAML.load(open("http://github.com/api/v1/yaml/search/tmbundle?start_value=#{page}"))['repositories']
|
205
|
+
results = []
|
206
|
+
until repositories.empty?
|
207
|
+
results += repositories.find_all{|result| result['name'].match(search_term)}
|
208
|
+
page += 1
|
209
|
+
repositories = YAML.load(open("http://github.com/api/v1/yaml/search/tmbundle?start_value=#{page}"))['repositories']
|
210
|
+
end
|
211
|
+
results.sort{|a,b| a['name'] <=> b['name']}
|
212
|
+
end
|
213
|
+
|
214
|
+
def git_clone(repo, name)
|
215
|
+
bundle_name = normalize_github_repo_name(name)
|
216
|
+
|
217
|
+
path = "#{install_bundles_path}/#{bundle_name}"
|
218
|
+
escaped_path = "#{e_sh(install_bundles_path)}/#{e_sh(bundle_name)}"
|
219
|
+
|
220
|
+
if File.directory?(path)
|
221
|
+
say "Sorry, that bundle is already installed. Please uninstall it first.", :red
|
222
|
+
exit
|
223
|
+
end
|
224
|
+
|
225
|
+
%[git clone "git://github.com/#{url_escape(repo)}/#{url_escape(name)}.git" #{escaped_path} 2>&1]
|
180
226
|
end
|
181
|
-
|
227
|
+
|
182
228
|
end
|
183
229
|
|
184
230
|
# TODO: create a "monument to personal cleverness" by class-izing everything?
|
185
231
|
# class TextMateBundle
|
186
232
|
# def self.find_local(bundle_name)
|
187
|
-
#
|
233
|
+
#
|
188
234
|
# end
|
189
|
-
#
|
235
|
+
#
|
190
236
|
# def self.find_remote(bundle_name)
|
191
|
-
#
|
237
|
+
#
|
192
238
|
# end
|
193
239
|
# attr_reader :name
|
194
240
|
# attr_reader :location
|
@@ -198,20 +244,20 @@ end
|
|
198
244
|
# @location = location
|
199
245
|
# @scm = scm
|
200
246
|
# end
|
201
|
-
#
|
247
|
+
#
|
202
248
|
# def install!
|
203
|
-
#
|
249
|
+
#
|
204
250
|
# end
|
205
|
-
#
|
251
|
+
#
|
206
252
|
# def uninstall!
|
207
|
-
#
|
253
|
+
#
|
208
254
|
# end
|
209
|
-
#
|
210
|
-
#
|
255
|
+
#
|
256
|
+
#
|
211
257
|
# def installed?
|
212
258
|
# # List all the installed versions, and where they're at
|
213
259
|
# end
|
214
|
-
#
|
260
|
+
#
|
215
261
|
# # TODO: dirty? method to show if there are any deltas
|
216
262
|
# end
|
217
263
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wycats-textmate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yehuda Katz
|
@@ -9,11 +9,12 @@ autorequire: textmate
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-08-03 00:00:00 -07:00
|
13
13
|
default_executable: textmate
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: thor
|
17
|
+
type: :runtime
|
17
18
|
version_requirement:
|
18
19
|
version_requirements: !ruby/object:Gem::Requirement
|
19
20
|
requirements:
|
@@ -35,8 +36,9 @@ files:
|
|
35
36
|
- README.markdown
|
36
37
|
- Rakefile
|
37
38
|
- bin/textmate
|
38
|
-
has_rdoc:
|
39
|
+
has_rdoc: false
|
39
40
|
homepage: http://yehudakatz.com
|
41
|
+
licenses:
|
40
42
|
post_install_message:
|
41
43
|
rdoc_options: []
|
42
44
|
|
@@ -57,9 +59,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
59
|
requirements: []
|
58
60
|
|
59
61
|
rubyforge_project:
|
60
|
-
rubygems_version: 1.
|
62
|
+
rubygems_version: 1.3.5
|
61
63
|
signing_key:
|
62
|
-
specification_version:
|
64
|
+
specification_version: 3
|
63
65
|
summary: Command-line textmate package manager
|
64
66
|
test_files: []
|
65
67
|
|