rleber-textmate 0.9.7.1
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/LICENSE +20 -0
- data/README.markdown +47 -0
- data/bin/textmate +7 -0
- data/lib/textmate.rb +14 -0
- data/lib/textmate/bundle.rb +13 -0
- data/lib/textmate/commands.rb +280 -0
- data/lib/textmate/main.rb +511 -0
- data/lib/textmate/repository.rb +29 -0
- data/spec/list_spec.rb +526 -0
- data/spec/locations_spec.rb +91 -0
- data/spec/spec_helper.rb +394 -0
- metadata +94 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# TextMateBundleManager Repository class
|
4
|
+
|
5
|
+
require 'delegate'
|
6
|
+
|
7
|
+
class TextMateBundleManager
|
8
|
+
class Repository < DelegateClass(Array)
|
9
|
+
attr_accessor :bundles
|
10
|
+
def initialize(options={})
|
11
|
+
@bundles = options[:bundles] || []
|
12
|
+
super(@bundles)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class TextMateRepository < Repository
|
17
|
+
end
|
18
|
+
|
19
|
+
class RemoteRepository < Repository
|
20
|
+
attr_accessor :location
|
21
|
+
def initialize(options={})
|
22
|
+
super(options)
|
23
|
+
@location = options[:location]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class SVNRepository < RemoteRepository
|
28
|
+
end
|
29
|
+
end
|
data/spec/list_spec.rb
ADDED
@@ -0,0 +1,526 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
EMPTY_LOCAL_BUNDLES = {}
|
4
|
+
|
5
|
+
SIMPLE_LOCAL_BUNDLES = {
|
6
|
+
:user => [
|
7
|
+
{:name=>"user_bundle1", :scm=>:github, :status=>'ahead 1', :source=>'source_u1'},
|
8
|
+
{:name=>"user_bundle2", :scm=>:github, :status=>'behind 2', :source=>'source_u2'},
|
9
|
+
{:name=>"bundle3", :scm=>:svn, :status=>'dirty', :source=>'source_3'},
|
10
|
+
],
|
11
|
+
:system => [
|
12
|
+
{:name=>"system_bundle1", :scm=>:svn, :status=>'dirty', :source=>'source_s1'},
|
13
|
+
{:name=>"bundle3", :scm=>:github, :status=>'ahead 1, behind 3', :source=>'source_3'},
|
14
|
+
],
|
15
|
+
:app => [],
|
16
|
+
}
|
17
|
+
|
18
|
+
describe TextMateBundleManager do
|
19
|
+
describe "list" do
|
20
|
+
|
21
|
+
def run_list(options={})
|
22
|
+
locations = options[:locations]
|
23
|
+
bundles = options[:bundles]
|
24
|
+
arguments = options[:arguments] || []
|
25
|
+
stub_local_bundles(locations, bundles)
|
26
|
+
@raw_list = capture(:stdout) { TextMateBundleManager.start(["list"] + arguments) }.split("\n")
|
27
|
+
@list = strip_leading_blank_lines(@raw_list)
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "with no bundles" do
|
31
|
+
it "should list nothing" do
|
32
|
+
run_list :bundles=>EMPTY_LOCAL_BUNDLES
|
33
|
+
@raw_list.size.should == 0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def strip_leading_blank_lines(list)
|
38
|
+
found_non_blank = false
|
39
|
+
new_list = []
|
40
|
+
list.each do |line|
|
41
|
+
next if !found_non_blank && line.blank?
|
42
|
+
found_non_blank = true
|
43
|
+
new_list << line
|
44
|
+
end
|
45
|
+
new_list
|
46
|
+
end
|
47
|
+
|
48
|
+
def list
|
49
|
+
@list
|
50
|
+
end
|
51
|
+
|
52
|
+
def non_heading_lines(list=nil)
|
53
|
+
list ||= @raw_list
|
54
|
+
non_headings = []
|
55
|
+
list.each_with_index do |line, i|
|
56
|
+
non_headings << line unless heading_line?(list, i)
|
57
|
+
end
|
58
|
+
non_headings
|
59
|
+
end
|
60
|
+
|
61
|
+
def break_lines(list=nil)
|
62
|
+
list ||= @raw_list
|
63
|
+
list.map{|line| line.split(break_pattern)}
|
64
|
+
end
|
65
|
+
|
66
|
+
def bundle_table(list=nil)
|
67
|
+
break_lines(non_heading_lines(list))
|
68
|
+
end
|
69
|
+
|
70
|
+
def bundles(list=nil)
|
71
|
+
bundle_table(list).map{|line| line[bundle_column]}
|
72
|
+
end
|
73
|
+
|
74
|
+
describe " --no-flat" do
|
75
|
+
|
76
|
+
def heading_relative_lines(pos=0,list=nil)
|
77
|
+
list ||= @raw_list
|
78
|
+
lines = []
|
79
|
+
list.each_with_index {|line, i| lines << list[i-1+pos] if line =~ /^-+$/ }
|
80
|
+
lines
|
81
|
+
end
|
82
|
+
|
83
|
+
def break_pattern
|
84
|
+
/\s{2,}/
|
85
|
+
end
|
86
|
+
|
87
|
+
def bundle_column
|
88
|
+
0
|
89
|
+
end
|
90
|
+
|
91
|
+
def headings(list=nil)
|
92
|
+
heading_relative_lines(0,list)
|
93
|
+
end
|
94
|
+
|
95
|
+
def bundles_for_location(location, list=nil)
|
96
|
+
found_location = false
|
97
|
+
list ||= @raw_list
|
98
|
+
bundles = []
|
99
|
+
list.each_with_index do |line, i|
|
100
|
+
if found_location
|
101
|
+
break if line.blank?
|
102
|
+
bundles << line unless line =~ /^-+$/
|
103
|
+
elsif line.match(location) && line =~ /\[.*\]/
|
104
|
+
found_location = true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
bundles
|
108
|
+
end
|
109
|
+
|
110
|
+
def heading_line?(list, i)
|
111
|
+
list[i].to_s =~ /^-+$/ || list[i+1].to_s =~ /^-+$/ || (list[i+2].to_s =~ /^-+$/ and list[i].blank?)
|
112
|
+
end
|
113
|
+
|
114
|
+
shared_examples_for "a non-flat list" do
|
115
|
+
it "starts with a heading" do
|
116
|
+
list.size.should >= 2 # Heading, plus underscores
|
117
|
+
list[0].should match /User Bundles/
|
118
|
+
list[1].should match /^-+$/
|
119
|
+
end
|
120
|
+
|
121
|
+
it "headings should include name and path" do
|
122
|
+
headings.each {|h| h.should match /^\s*(.*?)\s+\[.*\]\s*$/ }
|
123
|
+
end
|
124
|
+
|
125
|
+
it "headings should be preceded by a blank line" do
|
126
|
+
preceding_lines = heading_relative_lines(-1)
|
127
|
+
preceding_lines.each do |line|
|
128
|
+
line.should be_blank
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
it "headings should not be followed by a blank line" do
|
133
|
+
following_lines = heading_relative_lines(2)
|
134
|
+
following_lines.each do |line|
|
135
|
+
line.should_not be_blank
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should list some locations" do
|
140
|
+
headings.size.should > 0
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should not include locations with no bundles" do
|
144
|
+
headings.find {|h| h =~ /Application/}.should be_nil
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe " --no-status" do
|
149
|
+
describe "without a search term" do
|
150
|
+
before :each do
|
151
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES
|
152
|
+
end
|
153
|
+
|
154
|
+
it_behaves_like "a non-flat list"
|
155
|
+
|
156
|
+
it "has 1 column" do
|
157
|
+
bundle_table.should always_have_n_columns(1)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should list locations in order" do
|
161
|
+
headings[0].should match /User Bundles/
|
162
|
+
headings[1].should match /System Bundles/
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should include all the bundles, in order" do
|
166
|
+
bundles.should == %w{user_bundle1 user_bundle2 bundle3 system_bundle1 bundle3}
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "with a search term" do
|
171
|
+
describe "that is approximate" do
|
172
|
+
describe "and is found" do
|
173
|
+
before :each do
|
174
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle2']
|
175
|
+
end
|
176
|
+
|
177
|
+
it_behaves_like "a non-flat list"
|
178
|
+
|
179
|
+
it "has one entry" do
|
180
|
+
bundle_table.size == 1
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "and is not found" do
|
185
|
+
before :each do
|
186
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['foo']
|
187
|
+
end
|
188
|
+
|
189
|
+
it "prints nothing" do
|
190
|
+
@raw_list.size == 0
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "that is exact" do
|
196
|
+
describe "and is found" do
|
197
|
+
before :each do
|
198
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle3', '--exact']
|
199
|
+
end
|
200
|
+
|
201
|
+
it_behaves_like "a non-flat list"
|
202
|
+
|
203
|
+
it "has one entry" do
|
204
|
+
bundle_table.size == 1
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "and is not found" do
|
209
|
+
before :each do
|
210
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle2', '--exact']
|
211
|
+
end
|
212
|
+
|
213
|
+
it "prints nothing" do
|
214
|
+
@raw_list.size == 0
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe " --status" do
|
222
|
+
describe "without a search term" do
|
223
|
+
|
224
|
+
def heading_line?(list, i)
|
225
|
+
list[i-1].to_s =~ /^-+$/ || list[i].to_s =~ /^-+$/ || list[i+1].to_s =~ /^-+$/ || (list[i+2].to_s =~ /^-+$/ and list[i].blank?)
|
226
|
+
end
|
227
|
+
|
228
|
+
before :each do
|
229
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['--status']
|
230
|
+
end
|
231
|
+
|
232
|
+
it_behaves_like "a non-flat list"
|
233
|
+
|
234
|
+
it "has column headings after each heading" do
|
235
|
+
column_headings = heading_relative_lines(2)
|
236
|
+
column_headings.each {|line| line.should =~ /^\s*Name\s+SCM\s+Status\s+Source\s*$/ }
|
237
|
+
end
|
238
|
+
|
239
|
+
it "has 4 columns for each bundle" do
|
240
|
+
bundle_table.should always_have_n_columns(4)
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should list locations in order" do
|
244
|
+
headings[0].should match /User Bundles/
|
245
|
+
headings[1].should match /System Bundles/
|
246
|
+
end
|
247
|
+
|
248
|
+
it "should include all the bundles, in order" do
|
249
|
+
bundles.should == %w{user_bundle1 user_bundle2 bundle3 system_bundle1 bundle3}
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "with a search term" do
|
254
|
+
describe "that is approximate" do
|
255
|
+
describe "and is found" do
|
256
|
+
before :each do
|
257
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle2']
|
258
|
+
end
|
259
|
+
|
260
|
+
it_behaves_like "a non-flat list"
|
261
|
+
|
262
|
+
it "has one entry" do
|
263
|
+
bundle_table.size == 1
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "and is not found" do
|
268
|
+
before :each do
|
269
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['foo']
|
270
|
+
end
|
271
|
+
|
272
|
+
it "prints nothing" do
|
273
|
+
@raw_list.size == 0
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
describe "that is exact" do
|
279
|
+
describe "and is found" do
|
280
|
+
before :each do
|
281
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle3', '--exact']
|
282
|
+
end
|
283
|
+
|
284
|
+
it_behaves_like "a non-flat list"
|
285
|
+
|
286
|
+
it "has one entry" do
|
287
|
+
bundle_table.size == 1
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
describe "and is not found" do
|
292
|
+
before :each do
|
293
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle2', '--exact']
|
294
|
+
end
|
295
|
+
|
296
|
+
it "prints nothing" do
|
297
|
+
@raw_list.size == 0
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
describe " --flat" do
|
306
|
+
def heading_line?(list, i)
|
307
|
+
i == 0
|
308
|
+
end
|
309
|
+
|
310
|
+
def break_pattern
|
311
|
+
/\s*\|\s*/
|
312
|
+
end
|
313
|
+
|
314
|
+
def bundle_column
|
315
|
+
1
|
316
|
+
end
|
317
|
+
|
318
|
+
def locations(table=nil)
|
319
|
+
table ||= @table
|
320
|
+
locations = []
|
321
|
+
last_location = nil
|
322
|
+
table[1..-1].each_with_index do |cells, i|
|
323
|
+
locations << cells[0] if cells[0] != last_location
|
324
|
+
last_location = cells[0]
|
325
|
+
end
|
326
|
+
locations
|
327
|
+
end
|
328
|
+
|
329
|
+
shared_examples_for "a flat list" do
|
330
|
+
it "contains no location headings" do
|
331
|
+
list.select{|line| line =~ /-{2,}/ }.size.should == 0 # Look for ---- lines
|
332
|
+
end
|
333
|
+
|
334
|
+
it "should contain no blank lines" do
|
335
|
+
@raw_list.select{|line| line.blank? }.size.should == 0
|
336
|
+
end
|
337
|
+
|
338
|
+
it "should list some locations" do
|
339
|
+
locations.size.should > 0
|
340
|
+
end
|
341
|
+
|
342
|
+
it "should not include locations with no bundles" do
|
343
|
+
locations.should_not include "Application"
|
344
|
+
end
|
345
|
+
|
346
|
+
it "should begin with column headings" do
|
347
|
+
@table.first[0,2].should == %w{Location Bundle}
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
describe " --no-status" do
|
352
|
+
describe "without a search term" do
|
353
|
+
before :each do
|
354
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['--flat']
|
355
|
+
@table = break_lines
|
356
|
+
end
|
357
|
+
|
358
|
+
it_should_behave_like "a flat list"
|
359
|
+
|
360
|
+
it "has 2 columns" do
|
361
|
+
bundle_table.should always_have_n_columns(2)
|
362
|
+
end
|
363
|
+
|
364
|
+
it "should list locations in order" do
|
365
|
+
locs = locations
|
366
|
+
locs[0].should == "User"
|
367
|
+
locs[1].should == "System"
|
368
|
+
end
|
369
|
+
|
370
|
+
it "should include all the bundles, in order" do
|
371
|
+
@table.map{|row| row[1]}[1..-1].should == %w{user_bundle1 user_bundle2 bundle3 system_bundle1 bundle3}
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
describe "with a search term" do
|
376
|
+
describe "that is approximate" do
|
377
|
+
describe "and is found" do
|
378
|
+
before :each do
|
379
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle2', '--flat']
|
380
|
+
@table = break_lines
|
381
|
+
end
|
382
|
+
|
383
|
+
it_behaves_like "a flat list"
|
384
|
+
|
385
|
+
it "has at least one entry" do
|
386
|
+
bundle_table.size >= 1
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
describe "and is not found" do
|
391
|
+
before :each do
|
392
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['foo', '--flat']
|
393
|
+
@table = break_lines
|
394
|
+
end
|
395
|
+
|
396
|
+
it "prints nothing" do
|
397
|
+
@raw_list.size == 0
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
|
402
|
+
describe "that is exact" do
|
403
|
+
describe "and is found" do
|
404
|
+
before :each do
|
405
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle3', '--flat', '--exact']
|
406
|
+
@table = break_lines
|
407
|
+
end
|
408
|
+
|
409
|
+
it_behaves_like "a flat list"
|
410
|
+
|
411
|
+
it "has at least one entry" do
|
412
|
+
bundle_table.size >= 1
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
describe "and is not found" do
|
417
|
+
before :each do
|
418
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle2', '--flat', '--exact']
|
419
|
+
@table = break_lines
|
420
|
+
end
|
421
|
+
|
422
|
+
it "prints nothing" do
|
423
|
+
@raw_list.size == 0
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
describe " --status" do
|
431
|
+
describe "without a search term" do
|
432
|
+
before :each do
|
433
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['--flat', '--status']
|
434
|
+
@table = break_lines
|
435
|
+
end
|
436
|
+
|
437
|
+
it_should_behave_like "a flat list"
|
438
|
+
|
439
|
+
it "should list locations in order" do
|
440
|
+
locs = locations
|
441
|
+
locs[0].should == "User"
|
442
|
+
locs[1].should == "System"
|
443
|
+
end
|
444
|
+
|
445
|
+
it "should include all the bundles, in order" do
|
446
|
+
@table.map{|row| row[1]}[1..-1].should == %w{user_bundle1 user_bundle2 bundle3 system_bundle1 bundle3}
|
447
|
+
end
|
448
|
+
|
449
|
+
it "has 5 columns" do
|
450
|
+
bundle_table.should always_have_n_columns(5)
|
451
|
+
end
|
452
|
+
|
453
|
+
it "should have correct column headings" do
|
454
|
+
@table.first.should == %w{Location Bundle SCM Status Source}
|
455
|
+
end
|
456
|
+
|
457
|
+
it "should always have a correct SCM entry" do
|
458
|
+
bundle_table.should always_match_in_column(2, /^(-|svn|github)$/)
|
459
|
+
end
|
460
|
+
|
461
|
+
it "should always have a correct status entry" do
|
462
|
+
bundle_table.should always_match_in_column(3, /^(dirty|ahead\s+\d+|behind\s+\d+|ahead\s+\d+, behind\s+\d+)$/)
|
463
|
+
end
|
464
|
+
|
465
|
+
it "should always have a correct source entry" do
|
466
|
+
bundle_table.should always_match_in_column(4, /^(source_.?\d)$/)
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
describe "with a search term" do
|
471
|
+
describe "that is approximate" do
|
472
|
+
describe "and is found" do
|
473
|
+
before :each do
|
474
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle2', '--flat', '--status']
|
475
|
+
@table = break_lines
|
476
|
+
end
|
477
|
+
|
478
|
+
it_behaves_like "a flat list"
|
479
|
+
|
480
|
+
it "has at least one entry" do
|
481
|
+
bundle_table.size >= 1
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
describe "and is not found" do
|
486
|
+
before :each do
|
487
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['foo', '--flat', '--status']
|
488
|
+
@table = break_lines
|
489
|
+
end
|
490
|
+
|
491
|
+
it "prints nothing" do
|
492
|
+
@raw_list.size == 0
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
describe "that is exact" do
|
498
|
+
describe "and is found" do
|
499
|
+
before :each do
|
500
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle3', '--flat', '--exact', '--status']
|
501
|
+
@table = break_lines
|
502
|
+
end
|
503
|
+
|
504
|
+
it_behaves_like "a flat list"
|
505
|
+
|
506
|
+
it "has at least one entry" do
|
507
|
+
bundle_table.size >= 1
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
describe "and is not found" do
|
512
|
+
before :each do
|
513
|
+
run_list :bundles=>SIMPLE_LOCAL_BUNDLES, :arguments=>['bundle2', '--flat', '--exact', '--status']
|
514
|
+
@table = break_lines
|
515
|
+
end
|
516
|
+
|
517
|
+
it "prints nothing" do
|
518
|
+
@raw_list.size == 0
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|
524
|
+
end
|
525
|
+
end
|
526
|
+
end
|