wycats-textmate 0.9.1 → 0.9.2

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.
Files changed (4) hide show
  1. data/README.markdown +22 -12
  2. data/Rakefile +4 -4
  3. data/bin/textmate +100 -34
  4. metadata +4 -4
data/README.markdown CHANGED
@@ -1,31 +1,41 @@
1
- textmate
2
- ========
1
+ # textmate
3
2
 
4
3
  A binary that provides package management for TextMate.
5
4
 
6
- Usage
7
- =====
5
+ # Usage
8
6
 
9
7
  `textmate [COMMAND] [*PARAMS]`
10
8
 
11
9
  Textmate bundles are automatically reloaded after install or uninstall operations.
12
10
 
11
+ ## List available remote bundles
12
+
13
13
  `textmate remote [SEARCH]`
14
- ------------------------
15
14
 
16
- List all of the available bundles in the remote repository that have a substring `search`. By default, list all bundles.
15
+ List all of the available bundles in the remote repository, optionally filtering by `search`.
16
+
17
+ ## List installed bundles
18
+
19
+ `textmate list [SEARCH]`
17
20
 
18
- `textmate list`
19
- --------------------
21
+ List all of the bundles that are installed on the local system, optionally filtering by `search`.
20
22
 
21
- List all of the bundles that are installed on the local system.
23
+ ## Installing new bundles
22
24
 
23
25
  `textmate install NAME [SOURCE]`
24
- -----------------------
25
26
 
26
- Installs a bundle from the remote repository. SOURCE filters known remote bundle locations.
27
+ Installs a bundle from the remote repository. SOURCE filters known remote bundle locations.
28
+ For example, if you want to install the "Ruby on Rails" bundle off GitHub, you'd type the following:
29
+
30
+ `textmate install "Ruby on Rails" GitHub`
31
+
32
+ Available remote bundle locations are:
33
+ * Macromates Trunk
34
+ * Macromates Review
35
+ * GitHub
36
+
37
+ ## Uninstalling bundles
27
38
 
28
39
  `textmate uninstall NAME`
29
- -------------------------
30
40
 
31
41
  Uninstalls a bundle from the local repository.
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ require 'rake/gempackagetask'
3
3
  require 'date'
4
4
 
5
5
  GEM = "textmate"
6
- GEM_VERSION = "0.9.1"
6
+ GEM_VERSION = "0.9.2"
7
7
  AUTHOR = "Yehuda Katz"
8
8
  EMAIL = "wycats@gmail.com"
9
9
  HOMEPAGE = "http://yehudakatz.com"
@@ -21,11 +21,11 @@ spec = Gem::Specification.new do |s|
21
21
  s.email = EMAIL
22
22
  s.homepage = HOMEPAGE
23
23
 
24
- s.add_dependency "thor", ">= 0.9.1"
24
+ s.add_dependency "thor", ">= 0.9.2"
25
25
 
26
- s.require_path = 'lib'
26
+ s.require_path = 'bin' # Yes, it's a hack, but otherwise gem complains on install
27
27
  s.autorequire = GEM
28
- s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("{bin,lib,specs}/**/*")
28
+ s.files = %w(LICENSE README.markdown Rakefile) + Dir.glob("{bin,specs}/**/*")
29
29
  s.bindir = "bin"
30
30
  s.executables = %w( textmate )
31
31
  end
data/bin/textmate CHANGED
@@ -3,39 +3,51 @@
3
3
  require "fileutils"
4
4
  require "rubygems"
5
5
  require "thor"
6
+ require "open-uri"
7
+ require "yaml"
6
8
 
7
9
  class TextmateInstaller < Thor
8
10
 
9
11
  # CHANGED: renamed list to remote. Could there be a better name?
10
12
  desc "remote [SEARCH]", "Lists all the matching remote bundles"
11
- def remote(limit = "")
12
- limit = Regexp.new(".*#{limit}.*", "i")
13
+ def remote(search_term = "")
14
+ search_term = Regexp.new(".*#{search_term}.*", "i")
13
15
 
14
16
  remote_bundle_locations.each do |name,location|
15
17
  puts "\n" << name.to_s << " Remote Bundles\n" << name.to_s.gsub(/./,'-') << '---------------'
16
18
 
17
- results = %x[svn list #{e_sh location[:url]}] if location[:scm]==:svn
18
- puts results.map {|x| x.split(".")[0]}.select {|x| x =~ limit}.join("\n") if results
19
+ results = case location[:scm]
20
+ when :svn
21
+ %x[svn list #{e_sh location[:url]}].map {|x| x.split(".")[0]}.select {|x| x =~ search_term}.join("\n")
22
+ when :git
23
+ 'git remotes not implemented yet'
24
+ when :github
25
+ find_github_bundles(search_term).map {|result|
26
+ "%s (by %s)" %
27
+ [
28
+ normalize_github_repo_name(result['name']).split('.').first,
29
+ result['url'][/github\.com\/([a-zA-Z0-9]+)\//, 1] # Extract the username out of the repo URL
30
+ ]
31
+ }
32
+ end
19
33
 
20
- puts 'git remotes not implemented yet' if location[:scm]==:git
34
+ puts results
21
35
  end
22
36
  end
23
37
 
24
38
  desc "list [SEARCH]", "lists all the bundles installed locally"
25
- def list(limit = "")
26
- limit = Regexp.new(".*#{limit}.*", "i")
39
+ def list(search_term = "")
40
+ search_term = Regexp.new(".*#{search_term}.*", "i")
27
41
 
28
42
  local_bundle_paths.each do |name,bundles_path|
29
43
  puts "\n" << name.to_s << " Bundles\n" << name.to_s.gsub(/./,'-') << '--------'
30
44
  puts Dir["#{e_sh bundles_path}/*.tmbundle"].map {|x| x.split("/").last.split(".").first}.
31
- select {|x| x =~ limit}.join("\n")
45
+ select {|x| x =~ search_term}.join("\n")
32
46
  end
33
47
  end
34
48
 
35
- # TODO: Add a DESTINATION option to decide where to install. Maybe make some sort of ~/.textmate-cli config file?
36
49
  desc "install NAME [SOURCE]", "install a bundle"
37
50
  def install(bundle_name, remote_bundle_location_name=nil)
38
- # TODO: Add an option to remove all other versions of the same bundle
39
51
  FileUtils.mkdir_p install_bundles_path
40
52
  puts "Checking out #{bundle_name}..."
41
53
 
@@ -44,66 +56,99 @@ class TextmateInstaller < Thor
44
56
  remote_bundle_locations.each do |remote_name,location|
45
57
  next unless remote_name.to_s.downcase.include? remote_bundle_location_name.to_s.downcase if remote_bundle_location_name
46
58
 
47
- cmd = 'echo "git remotes not implemented yet"' if location[:scm]==:git
48
- cmd = %[svn co #{e_sh location[:url]}/#{e_sh bundle_name}.tmbundle #{e_sh install_bundles_path}/#{e_sh bundle_name}.tmbundle 2>&1] if location[:scm]==:svn
59
+ cmd = case location[:scm]
60
+ when :git
61
+ 'echo "git remotes not implemented yet"'
62
+ when :svn
63
+ %[svn co #{e_sh location[:url]}/#{e_sh bundle_name}.tmbundle #{e_sh install_bundles_path}/#{e_sh bundle_name}.tmbundle 2>&1]
64
+ when :github
65
+ repos = find_github_bundles(denormalize_github_repo_name(bundle_name))
66
+
67
+ # Handle possible multiple Repos with the same name
68
+ case repos.size
69
+ when 0
70
+ 'echo "Sorry, no such bundle found"'
71
+ when 1
72
+ %[git clone #{e_sh repos.first['url'].sub('http', 'git') + '.git'} #{e_sh install_bundles_path}/#{e_sh bundle_name}.tmbundle 2>&1]
73
+ else
74
+ puts "Multiple bundles with that name found. Please choose which one you want to install:"
75
+ repos.each_with_index {|repo, idx|
76
+ puts "%d: %s by %s" %
77
+ [
78
+ idx + 1,
79
+ normalize_github_repo_name(repo['name']),
80
+ repo['url'][/github\.com\/([a-zA-Z0-9]+)\//, 1]
81
+ ]
82
+ }
83
+ print "Your choice: "
84
+
85
+ # Since to_i defaults to 0, we have to use Integer
86
+ choice = Integer(STDIN.gets.chomp) rescue nil
87
+ until choice && (0...repos.size).include?( choice - 1 ) do
88
+ print "Sorry, invalid choice. Please enter a valid number or Ctrl+C to stop: "
89
+ choice = Integer(STDIN.gets.chomp) rescue nil
90
+ end
91
+
92
+ %[git clone #{e_sh repos[choice - 1]['url'].sub('http', 'git') + '.git'} #{e_sh install_bundles_path}/#{e_sh bundle_name}.tmbundle 2>&1]
93
+ end
94
+ end
95
+
49
96
  res = %x{#{cmd}}
50
97
 
51
- puts cmd, res.gsub(/^/,' ') #if verbose # TODO: Implement a verbose mode to toggle showing all the gory details
98
+ puts cmd, res.gsub(/^/,' ')
52
99
 
53
100
  installed=true and break if res =~ /Checked out revision|Initialized empty Git repository/
54
101
  end
55
- abort 'Not Installed' unless installed # TODO: Offer suggestions for alternate bundles with similar names. Maybe let them choose
102
+ abort 'Not Installed' unless installed
56
103
 
57
- puts "Reloading Bundles..."
58
- reload_textmate!
59
- puts "Done."
104
+ reload :verbose => true
60
105
  end
61
106
 
62
107
  desc "uninstall NAME", "uninstall a bundle"
63
108
  def uninstall(bundle_name)
64
109
  puts "Removing bundle..."
65
- # FIXME: Move deleted bundles to the trash instead of rm_rf-ing them?
66
110
  # When moving to the trash, maybe move the bundle into a trash/disabled_bundles subfolder
67
111
  # named as the bundles_path key. Just in case there are multiple versions of
68
112
  # the same bundle in multiple bundle paths
69
113
  local_bundle_paths.each do |name,bundles_path|
70
- FileUtils.rm_rf("#{bundles_path}/#{bundle_name}.tmbundle")
114
+ bundle_path = "#{bundles_path}/#{bundle_name}.tmbundle"
115
+ if File.exist? bundle_path
116
+ %x[osascript -e 'tell application "Finder" to move the POSIX file "#{bundle_path}" to trash']
117
+ end
71
118
  end
72
- puts "Reloading bundles..."
73
- reload_textmate!
74
- puts "Done."
119
+
120
+ reload :verbose => true
75
121
  end
76
122
 
77
- private
78
- def reload_textmate!
123
+ desc "reload", "Reloads TextMate Bundles"
124
+ method_options :verbose => :boolean
125
+ def reload(opts = {})
126
+ puts "Reloading bundles..." if opts[:verbose]
79
127
  %x[osascript -e 'tell app "TextMate" to reload bundles']
128
+ puts "Done." if opts[:verbose]
80
129
  end
81
130
 
131
+ private
82
132
  def remote_bundle_locations
83
- { :'Marcomates Trunk' => {:scm => :svn, :url => 'http://macromates.com/svn/Bundles/trunk/Bundles'},
84
- :'Marcomates Review' => {:scm => :svn, :url => 'http://macromates.com/svn/Bundles/trunk/Review/Bundles'},
133
+ { :'Macromates Trunk' => {:scm => :svn, :url => 'http://macromates.com/svn/Bundles/trunk/Bundles'},
134
+ :'Macromates Review' => {:scm => :svn, :url => 'http://macromates.com/svn/Bundles/trunk/Review/Bundles'},
85
135
 
86
- # TODO: Add Git support to remote_bundle_locations. Define some sort of standard way of listing git repos, checkout how rubygems does it
87
136
  # :'Bunch of Git Bundles' => {:scm => :git, :url => 'git://NotImplemented'},
88
137
 
89
- # TODO: Add GitHub support as a remote_bundle_location
90
- # This will require fetching the html of the search page, scanning for urls and converting them to git urls
91
- # :'GitHub' => {:scm => :github, :url => 'http://github.com/search?q=tmbundle'},
138
+ :'GitHub' => {:scm => :github, :url => 'http://github.com/search?q=tmbundle'},
92
139
  }
93
- # TODO: Add some way to add more custom remotes
94
140
  end
95
141
 
96
142
  def local_bundle_paths
97
143
  { :Application => '/Applications/TextMate.app/Contents/SharedSupport/Bundles',
98
144
  :User => "#{ENV["HOME"]}/Library/Application Support/TextMate/Bundles",
99
145
  :System => '/Library/Application Support/TextMate/Bundles',
100
- :'User Pristine' => "#{ENV["HOME"]}/Library/Application Support/TextMate/Pristine Copy",
101
- :'System Pristine' => '/Library/Application Support/TextMate/Pristine Copy',
146
+ :'User Pristine' => "#{ENV["HOME"]}/Library/Application Support/TextMate/Pristine Copy/Bundles",
147
+ :'System Pristine' => '/Library/Application Support/TextMate/Pristine Copy/Bundles',
102
148
  }
103
149
  end
104
150
 
105
151
  def install_bundles_path
106
- #TODO: Add some way for the user to configure where they'd prefer to install bundles
107
152
  local_bundle_paths[:'User Pristine']
108
153
  end
109
154
 
@@ -113,6 +158,27 @@ class TextmateInstaller < Thor
113
158
  str.to_s.gsub(/(?=[^a-zA-Z0-9_.\/\-\x7F-\xFF\n])/, '\\').gsub(/\n/, "'\n'").sub(/^$/, "''")
114
159
  end
115
160
 
161
+ CAPITALIZATION_EXCEPTIONS = %w[tmbundle on]
162
+ # Convert a GitHub repo name into a "normal" TM bundle name
163
+ # e.g. ruby-on-rails-tmbundle => Ruby on Rails.tmbundle
164
+ def normalize_github_repo_name(name)
165
+ name = name.gsub("-", " ").split.each{|part| part.capitalize! unless CAPITALIZATION_EXCEPTIONS.include? part}.join(" ")
166
+ name[-9] = ?. if name =~ / tmbundle$/
167
+ name
168
+ end
169
+
170
+ # Does the opposite of normalize_github_repo_name
171
+ def denormalize_github_repo_name(name)
172
+ name += " tmbundle" unless name =~ / tmbundle$/
173
+ name.split(' ').each{|part| part.downcase!}.join(' ').gsub(' ', '-')
174
+ end
175
+
176
+ def find_github_bundles(search_term)
177
+ YAML.load(open('http://github.com/api/v1/yaml/search/tmbundle'))['repositories'].
178
+ find_all{|result| result['name'].match(search_term)}.
179
+ sort{|a,b| a['name'] <=> b['name']}
180
+ end
181
+
116
182
  end
117
183
 
118
184
  # TODO: create a "monument to personal cleverness" by class-izing everything?
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.1
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yehuda Katz
@@ -9,7 +9,7 @@ autorequire: textmate
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-05-19 00:00:00 -07:00
12
+ date: 2008-05-28 00:00:00 -07:00
13
13
  default_executable: textmate
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -19,7 +19,7 @@ dependencies:
19
19
  requirements:
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 0.9.1
22
+ version: 0.9.2
23
23
  version:
24
24
  description: Command-line textmate package manager
25
25
  email: wycats@gmail.com
@@ -41,7 +41,7 @@ post_install_message:
41
41
  rdoc_options: []
42
42
 
43
43
  require_paths:
44
- - lib
44
+ - bin
45
45
  required_ruby_version: !ruby/object:Gem::Requirement
46
46
  requirements:
47
47
  - - ">="