tmb 0.0.5 → 0.0.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.tar.gz.sig CHANGED
@@ -1 +1 @@
1
- I�-&5��h͸����h^%�Z�۱Ҡ{�M�Y�ӧ��=g��h\�2�/��cWOoݦX�>׹�[��� V�-����/���HS���Wmm������6ai�̈́�*�chi(O��^W����" �5��K�7?����L�'r�������e�D�6qS�:��#2��K歧͚�L��;�HS��^|k�j�a���G<F^���L)X���>hޛ̋@�ρqI�<�YɈ��.�l����U�{{PRHQ�2�#s
1
+ !��
data/CHANGELOG CHANGED
@@ -1,3 +1,4 @@
1
+ v0.0.6. We search ALL of the github repos now instead of just first 100
1
2
  v0.0.5. Bundles can now be installed with a full github repo path - avoid searching issues
2
3
  v0.0.4. Totally doing this wrong - Gem should be signed now
3
4
  v0.0.3. Totally doing this wrong - Gem should be signed now
data/Manifest CHANGED
@@ -1,6 +1,10 @@
1
1
  CHANGELOG
2
2
  LICENSE
3
- Manifest
4
3
  README.md
5
4
  Rakefile
6
5
  bin/tmb
6
+ lib/tmb.rb
7
+ lib/tmb/bundle.rb
8
+ lib/tmb/bundles.rb
9
+ lib/tmb/commands.rb
10
+ Manifest
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'echoe'
4
4
  #Echoe.new(File.basename(File.dirname(__FILE__)))
5
5
 
6
6
  App = "tmb"
7
- Version = "0.0.5"
7
+ Version = "0.0.6"
8
8
 
9
9
  Echoe.new(App, Version) do |p|
10
10
  p.name = App
data/bin/tmb CHANGED
@@ -1,527 +1,6 @@
1
- #!/usr/bin/env ruby -i
2
-
3
- # This script allows you to install textmate bundles from github like gems
4
- # You will need the "get_bundle" script to do the dirty work of pulling the repo and installing the script
1
+ #!/usr/bin/env ruby
5
2
 
6
3
  require 'rubygems'
7
- require 'json'
8
- require 'open-uri'
9
- require 'uri'
10
-
11
- module TM
12
-
13
- TextWrap = 78
14
- IndentSpacing = 10
15
- Indent = (" " * IndentSpacing)
16
- Justify = 15
17
- Delimiter = ": "
18
- BundleDirectory = "/Library/Application Support/TextMate/Bundles"
19
- App = File.basename(__FILE__)
20
-
21
- Help = <<-eos
22
-
23
- \033[1m#{App}\033[0m is a utility to search for textmate bundles, download and install
24
- them, all via a convenient command line interface, much like rubygems.
25
-
26
-
27
- Usage:
28
- ======================================
29
-
30
- # Search for bundles containing the word 'webrat' in
31
- # the title, description, or author's name.
32
-
33
- \033[1m#{App} search webrat\033[0m
34
-
35
-
36
- # Search for bundles containing the word 'rspec' OR
37
- # 'cucumber' OR 'shoulda' in their title, description,
38
- # or author's name.
39
-
40
- \033[1m#{App} search rspec cucumber shoulda\033[0m
41
-
42
-
43
- # Install a bundle containing the word rspec in its
44
- # search fields. If multiple matches exist, #{App}
45
- # will let you choose which version to install.
46
-
47
- \033[1m#{App} install rspec\033[0m
48
-
49
-
50
- # List all installed bundles
51
-
52
- \033[1m#{App} list\033[0m
53
-
54
-
55
- # Uninstall bundle matching 'json'. If you type in a
56
- # fragment and there are multiple installed bundles that begin
57
- # with that fragment, #{App} will let you choose which version
58
- # you'd like to destroy
59
-
60
- \033[1m#{App} uninstall json\033[0m
61
-
62
-
63
- # Tell textmate (if it's open) to reload its bundle information,
64
- # and update menus & controls accordingly
65
-
66
- \033[1m#{App} reload\033[0m
67
-
68
-
69
- # Print this help information
70
-
71
- \033[1m#{App} help\033[0m
72
-
73
-
74
-
75
- eos
76
-
77
- end
78
-
79
-
80
- class String
81
-
82
- def indent(indent=TM::Indent)
83
- indent + self
84
- end
85
-
86
- def text_wrap(width=TM::TextWrap, indent=TM::Indent)
87
- self.gsub /(.{1,#{width}})(\s+|\Z)/, "\\1\n".indent(indent)
88
- end
89
-
90
- def bold
91
- "\033[1m" + self + "\033[0m"
92
- end
93
-
94
- end
95
-
96
- module TM
97
-
98
- class Bundle
99
-
100
-
101
- attr_accessor :result, :repository, :install_output
102
-
103
-
104
- def initialize(result=nil, options={})
105
- @result = result
106
- @repository = options[:repo] || git_repo
107
- end
108
-
109
- def self.installed
110
- Dir.glob("#{BundleDirectory}/*.tmbundle").sort{|a,b| a.downcase <=> b.downcase }
111
- end
112
-
113
- def self.list
114
- installed.each do |b|
115
- puts File.basename(b)
116
- end
117
- end
118
-
119
- def self.select(bundle)
120
- installed.select{|b| b =~ Regexp.new(bundle + ".*\.tmbundle$") }
121
- end
122
-
123
- def self.uninstall(bundle)
124
- bundle_dir = File.basename(bundle)
125
- FileUtils.rm_r(File.join(BundleDirectory, bundle_dir))
126
- end
127
-
128
- def short_result
129
- {:description => result["description"], :repo => repository }
130
- end
131
-
132
- def bundle_name
133
- result["name"].gsub("tmbundle",'').gsub(/^[[:punct:]]+|[[:punct:]]+$/,'')
134
- end
135
-
136
- def git_repo
137
- "https://github.com/#{@result["username"]}/#{@result["name"]}.git"
138
- end
139
-
140
- def display_key(key, options={})
141
- defaults = {:ljust => Justify, :rjust => Justify, :delimiter => Delimiter, :key_prefix => "", :key_suffix => ""}
142
- options = defaults.merge options
143
-
144
- if options[:bold_key]
145
- options[:key_prefix] = "\033[1m" + options[:key_prefix]
146
- options[:key_suffix] = options[:key_suffix] +"\033[0m"
147
- end
148
- if options[:title].nil? || options[:title].strip.length == 0
149
- options[:title] = ""
150
- options[:delimiter] = ""#(" " * options[:delimiter].length)
151
- options[:ljust] = 0
152
- end
153
- options[:title] ||= key.to_s
154
- options[:key_prefix] + (options[:title].capitalize + options[:delimiter]).ljust(options[:ljust]) + options[:key_suffix]
155
- end
156
-
157
- def display_keypair(key, options={})
158
- defaults = {:title => key.to_s, :ljust => Justify, :rjust => Justify, :delimiter => Delimiter, :key_prefix => "", :key_suffix => "", :value_prefix => "", :value_suffix => ""}
159
- options = defaults.merge(options)
160
- if options[:bold]
161
- options[:bold_value] ||= true
162
- options[:bold_key] ||= true
163
- end
164
- if options[:bold_value]
165
- options[:value_prefix] = "\033[1m" + options[:value_prefix]
166
- options[:value_suffix] = options[:value_suffix] +"\033[0m"
167
- end
168
- [
169
- display_key(options[:title], options),
170
- options[:value_prefix] + ((options[:value] || (key.is_a?(Symbol) && self.methods.include?(key.to_s)) ? self.send(key) : @result[key.to_s]).to_s) + options[:value_suffix]
171
- ].compact.reject{|s| s.strip == "" }.join
172
- end
173
-
174
-
175
-
176
- def display_value(key, options={})
177
- display_keypair(key, options)
178
- end
179
-
180
- def extended_display(key, options={})
181
- #options[:indent] ||= true
182
- ed = display_value(key, options).to_s
183
- unless options[:indent] == false
184
- ed = ed.indent
185
- end
186
- if options[:wrap]
187
- ed = ed.text_wrap
188
- end
189
- if options[:newline]
190
- ed = ("\n" * options[:newline]) + ed
191
- end
192
- ed
193
- end
194
-
195
- def stats
196
- "\n" + [
197
- display_value(:followers, :ljust => Justify ),
198
- display_value(:forks, :ljust => Justify ),
199
- display_value(:watchers, :ljust => Justify )
200
- ].map{|v| v.indent(" " * (IndentSpacing + Justify))}.join("\n")
201
- end
202
-
203
- def short_stats
204
- "(" + ["followers", "forks", "watchers"].map{|s| result[s.to_s].to_s + " " + s.to_s}.join(", ") + ")"
205
- end
206
-
207
- def as_selection(index)
208
- "#{(index + 1).to_s}) #{git_repo.ljust(60)} \033[1m#{short_stats}\033[0m"
209
-
210
- end
211
-
212
- def display_map
213
- [
214
- {:v=> "name", :bold => true, :indent => true, :title => "", :value_prefix => "\e[1;32m"},
215
- {:v => "username", :title => "Author", :bold_value => true, :newline => 1},
216
- {:v => "homepage"},
217
- {:v => :repository, :bold_value => true},
218
- {:v => :stats, :delimiter => "", :title => ""},
219
- {:v => "created_at", :newline => 1},
220
- {:v=> "description", :indent => false, :newline => 2, :title => "", :wrap => true}
221
- ]
222
- end
223
-
224
- def to_s
225
- display_map.map{|d| extended_display(d.delete(:v), d) }.join("\n") + "\n"
226
- end
227
-
228
- def to_ss
229
- [
230
- "\033[1m" + display_value("name") + "\033[0m",
231
- display_value("username", :title => "Author").indent,
232
- display_value(:repository).indent,
233
- display_value("homepage").indent,
234
- display_value("followers").indent,
235
- display_value("followers").indent,
236
- display_value("followers").indent,
237
- display_value("created_at").indent,
238
- "\n" + result["description"].text_wrap
239
- ].join("\n")
240
- end
241
-
242
- def destination
243
- File.join(BundleDirectory, "#{bundle_name}.tmbundle")
244
- end
245
-
246
- def common_install_script
247
- <<-eos
248
- bundle_dir="#{BundleDirectory}"
249
- mkdir -p "$bundle_dir"
250
- file_name=$(echo -e #{@repository} | grep -o -P "[-\w\.]+$")
251
- bundle_name=$(echo -e $file_name | sed -E -e 's/\.[a-zA-Z0-9]+$//g' -e 's/\.tmbundle//g')
252
- dest="#{destination}"
253
- rm -Rf "$dest"
254
- eos
255
- end
256
-
257
- def git_install_script
258
- <<-eos
259
- #{common_install_script}
260
- git clone #{@repository} "$dest"
261
- osascript -e 'tell app "TextMate" to reload bundles'
262
- eos
263
- end
264
-
265
- def smart_extract_script(archive)
266
- <<-eos
267
- arch=#{archive}
268
- if [ -f $arch ]; then
269
- case $arch in
270
- *.tar.bz2) tar -jxvf $arch ;;
271
- *.tar.gz) tar -zxvf $arch ;;
272
- *.bz2) bunzip2 $arch ;;
273
- *.dmg) hdiutil mount $arch ;;
274
- *.gz) gunzip $arch ;;
275
- *.tar) tar -xvf $arch ;;
276
- *.tbz2) tar -jxvf $arch ;;
277
- *.tgz) tar -zxvf $arch ;;
278
- *.zip) unzip $arch ;;
279
- *.Z) uncompress $arch ;;
280
- *) echo "'$arch' cannot be extracted/mounted via smartextract()" ;;
281
- esac
282
- else
283
- echo "'$arch' is not a valid file"
284
- fi
285
- eos
286
- end
287
-
288
- def archive_install_script
289
- <<-eos
290
- #{common_install_script}
291
- cd $bundle_dir
292
- if [[ -n $bundle_name ]]
293
- then
294
- rm -R "$bundle_dir/$bundle_name"*
295
- fi
296
- curl -o "$bundle_dir/$file_name" $1
297
- #{ smart_extract_script('$bundle_dir/$file_name')}
298
- bundle=$(find $bundle_dir/$bundle_name | grep -P "tmbundle$")
299
- if [[ -n $bundle ]]
300
- then
301
- cp -R $bundle $bundle_dir
302
- fi
303
- non_bundles=$(find $bundle_dir -d 1 | grep -v -P "tmbundle$|^\.")
304
- echo $non_bundles | xargs -Ixxx rm -Rf "xxx"
305
- cd $current
306
- osascript -e 'tell app "TextMate" to reload bundles'
307
- eos
308
- end
309
-
310
- def install
311
- install_output = IO.popen(git_install_script).read
312
- end
313
-
314
-
315
- end
316
- end
317
-
318
-
319
-
320
-
321
-
322
- class TMBundles
323
-
324
- attr_accessor :response, :results, :search_terms, :full_set
325
-
326
-
327
- def initialize(search_terms=nil)
328
- @search_terms = search_terms
329
- @full_set = nil
330
- @results = []
331
- search
332
- end
333
-
334
- def self.handle_connection_error(e, url)
335
- error = e.class.name.split("::")
336
- exception = error[-1]
337
- lib = error[0]
338
- lib = lib == exception ? "OpenURI" : lib
339
- host = URI.parse(url).host
340
- error_message = case exception
341
- when "SocketError" : socket_error(e,url)
342
- when "HTTPError" : http_error(e,url)
343
- end
344
- puts error_message.
345
- gsub(/#URL/,url).
346
- gsub(/#LIB/,lib).
347
- gsub(/#MESSAGE/,e.message).
348
- gsub(/#EXCEPTION/,exception).
349
- gsub(/#HOST/,host)
350
- exit 0
351
- end
352
-
353
- def self.socket_error(e, url)
354
- <<-eos
355
-
356
- #LIB is raising a #EXCEPTION: \033[1m#{e.message}\033[0m
357
-
358
- Either \033[1m#HOST\033[0m is currently unavailable or your internet connection is down.
359
-
360
- (We were trying to access \033[1m#URL\033[0m)
361
-
362
- eos
363
- end
364
-
365
- def self.http_code_messages
366
- {
367
- "404" => "the page you're attempting to access doesn't exist"
368
- }
369
- end
370
-
371
- def self.http_error(e, url)
372
- <<-eos
373
-
374
- #LIB is raising an #EXCEPTION: \033[1m#MESSAGE\033[0m
375
-
376
- That means #{http_code_messages[e.message.match(/\d{3}/).to_s]}
377
-
378
- (We were trying to access \033[1m#URL\033[0m)
379
-
380
- eos
381
- end
382
-
383
- def search_description(terms=@search_terms)
384
- "Searching for \033[1m#{terms.to_a.join(', ')}\033[0m"
385
- end
386
-
387
- def put_search_description
388
- puts "\n" + search_description + "\n"
389
- end
390
-
391
-
392
- def short_result(result)
393
- {:description => result["description"], :repo => git_repo(result) }
394
- end
395
-
396
- def sample_response
397
- '{"repositories": [{"name": "haml", "username": "justin"}]}'
398
- end
399
-
400
- def search(search_terms = @search_terms, options={})
401
- bundle_suffix = "bundle"
402
- options[:additive] ||= true
403
- formatted_terms = search_terms.to_a.join =~ Regexp.new(bundle_suffix) ? search_terms.to_a.join : [bundle_suffix,search_terms.to_a].flatten.compact.join(' ')
404
- regex_terms = Regexp.new(search_terms.to_a.join("|"))
405
- search_url="http://github.com/api/v2/json/repos/search/#{URI.escape(formatted_terms)}"
406
- if search_terms.nil? && full_set.nil?
407
- begin
408
- response = open(search_url).read
409
- rescue => e
410
- self.class.handle_connection_error(e,search_url)
411
- end
412
- @full_set = JSON.parse(response)["repositories"]
413
- @full_set.each_with_index do |r,i|
414
- @full_set[i]["search_terms"] = r.values_at("username", "name", "description").join
415
- end
416
- else
417
- if options[:additive]
418
- @results += full_set.to_a.select{|r| r["search_terms"] =~ regex_terms}
419
- else
420
- @results = full_set.to_a.select{|r| r["search_terms"] =~ regex_terms}
421
- end
422
- end
423
- @results = @results.uniq
424
- current_results = search_terms.nil? ? full_set : results
425
- return current_results.uniq
426
- end
427
-
428
-
429
- def display_results(res=nil)
430
- res ||= results
431
- to_display = res || search(search_terms)
432
- to_display.sort{|a,b| a["name"].downcase <=> b["name"].downcase }.map{|r| TM::Bundle.new(r).to_s }.join("\n\n")
433
- end
434
-
435
- def bash_install_script_from_repo(repo)
436
- <<-eos
437
- bundle_dir="/Library/Application Support/TextMate/Bundles"
438
- mkdir -p "$bundle_dir"
439
- file_name=$(echo -e #{repo} | grep -o -P "[-\w\.]+$")
440
- bundle_name=$(echo -e $file_name | sed -E -e 's/\.[a-zA-Z0-9]+$//g' -e 's/\.tmbundle//g')
441
- dest=$bundle_dir/$bundle_name.tmbundle
442
- rm -Rf "$dest"
443
- git clone #{repo} "$dest"
444
- osascript -e 'tell app "TextMate" to reload bundles'
445
- eos
446
- end
447
-
448
- def install(repo)
449
- puts repo
450
- if repo.match(/^(http|git|https):.*\.git$/)
451
- matching_repo = TM::Bundle.new([], :repo => repo)
452
- elsif repo.match(/^(http|ftp|https):.*\.(zip|gz|tar.gz|bz2|tar.bz2)$/)
453
- matching_repo = TM::Bundle.new([], :repo => repo)
454
- else
455
- matching_repo = TM::Bundle.new(search(repo).first)
456
- end
457
- install_output = matching_repo.install
458
- puts install_output
459
- end
460
-
461
- end
462
-
463
- searcher = TMBundles.new
464
- search_terms = ARGV[1..-1]
465
- commands = ["install", "search", "reload","list", "uninstall","help"]
466
- tm_command = ARGV[0]
467
-
468
- unless commands.include?(ARGV[0])
469
- puts "You must use this command like 'tmbundles search {search terms}' or 'tmbundles install {package name or repository uri}'"
470
- exit 0
471
- end
472
-
473
- if tm_command == "uninstall"
474
- results = TM::Bundle.select(ARGV[1])
475
- if results.size > 1
476
- puts "\nYou are trying to uninstall multiple bundles. Select the bundle you wish to remove: \n\n"
477
- results.each_with_index do |r,i|
478
- puts "#{(i+1)}) #{r}"
479
- end
480
- print "\n\nMake your selection: "
481
- selection = STDIN.gets.chomp
482
- result = results[selection.to_i - 1]
4
+ require 'tmb'
483
5
 
484
- else
485
- result = results.first
486
- end
487
- puts "\nYou chose #{result}\n\nUninstalling...\n\n"
488
- removed = TM::Bundle.uninstall(result)
489
- puts "#{result} uninstalled" if removed
490
- elsif tm_command == "list"
491
- TM::Bundle.list
492
- elsif tm_command == "search"
493
- if search_terms.nil? or search_terms.length == 0
494
- searcher.search
495
- else
496
- search_terms.each{|term| searcher.search(term) }
497
- end
498
- puts "\n" + searcher.search_description(search_terms) + "\n\n" + searcher.display_results + "\n\n"
499
- elsif ARGV[0] == "install"
500
- if ARGV[1] =~ /^(https|git):\S*\.git$/
501
- TM::Bundle.new({},:repo => ARGV[1]).install
502
- exit 0
503
- end
504
- results = searcher.search(ARGV[1])
505
- if results.size == 0
506
- puts "No matches found"
507
- elsif results.size == 1
508
- TM::Bundle.new(results.first).install
509
- else
510
- puts "\nYour installation attempt found multiple bundles. Which of the following repositories would you like to install?\n\n"
511
- results.each_with_index do |r,i|
512
- b = TM::Bundle.new(r)
513
- puts b.as_selection(i)
514
- end
515
- print "\n\nMake your selection: "
516
- selection = STDIN.gets.chomp
517
- result = results[selection.to_i - 1]
518
- puts "\nYou chose #{selection}: #{result['name']}\n\nInstalling...\n\n"
519
- bundle = TM::Bundle.new(result)
520
- bundle.install
521
- puts "Bundle installed to #{bundle.destination}"
522
- end
523
- elsif ARGV[0] == "reload"
524
- IO.popen("osascript -e 'tell app \"TextMate\" to reload bundles'").read
525
- elsif ARGV[0] == "help"
526
- puts TM::Help
527
- end
6
+ TM::Commands.run(ARGV)