twig 1.0.1 → 1.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/twig/display.rb CHANGED
@@ -46,11 +46,22 @@ class Twig
46
46
  new_string
47
47
  end
48
48
 
49
- def branch_list_headers(header_options = { :color => :blue })
49
+ def branch_list_headers(header_options = {})
50
50
  columns_for_date_time = 5
51
51
  columns_per_property = 2
52
52
  branch_indicator_padding = ' ' * CURRENT_BRANCH_INDICATOR.size
53
53
 
54
+ header_options.merge!(
55
+ header_options.inject({}) do |opts, (key, value)|
56
+ if key == :header_color
57
+ opts[:color] = value
58
+ elsif key == :header_weight
59
+ opts[:weight] = value
60
+ end
61
+ opts
62
+ end
63
+ )
64
+
54
65
  out =
55
66
  column(' ', columns_for_date_time) <<
56
67
  Twig::Branch.all_properties.map do |property|
@@ -75,7 +86,7 @@ class Twig
75
86
  is_current_branch = branch.name == current_branch_name
76
87
 
77
88
  properties = Twig::Branch.all_properties.inject({}) do |result, property_name|
78
- property = get_branch_property(branch.name, property_name).strip
89
+ property = (get_branch_property(branch.name, property_name) || '').strip
79
90
  property = column(EMPTY_BRANCH_PROPERTY_INDICATOR) if property.empty?
80
91
  property.gsub!(/[\n\r]+/, ' ')
81
92
  result.merge(property_name => property)
@@ -111,7 +122,11 @@ class Twig
111
122
  string_options << WEIGHTS[options[:weight]] if options[:weight]
112
123
  return string if string_options.empty?
113
124
 
114
- "\033[#{string_options.join(';')}m#{string}\033[0m"
125
+ "\e[#{string_options.join(';')}m#{string}\e[0m"
126
+ end
127
+
128
+ def formatted_string_display_size(string)
129
+ string.gsub(/\e\[[0-9]+(;[0-9]+)?m/, '').size
115
130
  end
116
131
  end # module Display
117
132
  end
data/lib/twig/options.rb CHANGED
@@ -10,7 +10,8 @@ class Twig
10
10
  File.open(config_file_path) do |f|
11
11
  opts = f.read.split("\n").inject({}) do |hsh, opt|
12
12
  key, value = opt.split(':', 2)
13
- hsh.merge(key.strip => value.strip)
13
+ hsh[key.strip] = value.strip if key && value
14
+ hsh
14
15
  end
15
16
 
16
17
  opts.each do |key, value|
@@ -19,6 +20,7 @@ class Twig
19
20
  when 'except-branch' then set_option(:branch_except, value)
20
21
  when 'only-branch' then set_option(:branch_only, value)
21
22
  when 'max-days-old' then set_option(:max_days_old, value)
23
+ when 'header-style' then set_option(:header_style, value)
22
24
  end
23
25
  end
24
26
  end
@@ -36,6 +38,8 @@ class Twig
36
38
  options[:branch_except] = Regexp.new(value)
37
39
  when :branch_only
38
40
  options[:branch_only] = Regexp.new(value)
41
+ when :header_style
42
+ set_header_style_option(value)
39
43
  when :max_days_old
40
44
  if Twig::Util.numeric?(value)
41
45
  options[:max_days_old] = value.to_f
@@ -47,6 +51,27 @@ class Twig
47
51
  end
48
52
  end
49
53
 
54
+ def set_header_style_option(value)
55
+ style_values = value.split(/\s+/).map(&:to_sym)
56
+ colors = Twig::Display::COLORS.keys
57
+ weights = Twig::Display::WEIGHTS.keys
58
+ color = nil
59
+ weight = nil
60
+
61
+ style_values.each do |style_value|
62
+ if !color && colors.include?(style_value)
63
+ color = style_value
64
+ elsif !weight && weights.include?(style_value)
65
+ weight = style_value
66
+ else
67
+ abort %{The value `--header-style=#{value}` is invalid.}
68
+ end
69
+ end
70
+
71
+ options[:header_color] = color if color
72
+ options[:header_weight] = weight if weight
73
+ end
74
+
50
75
  def unset_option(key)
51
76
  options.delete(key)
52
77
  end
data/lib/twig/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Twig
2
- VERSION = '1.0.1'
2
+ VERSION = '1.1'
3
3
  end
@@ -101,17 +101,55 @@ describe Twig::Branch do
101
101
  end
102
102
 
103
103
  describe '#get_property' do
104
+ before :each do
105
+ @branch = Twig::Branch.new('test')
106
+ end
107
+
104
108
  it 'returns a property value' do
105
- branch = Twig::Branch.new('test')
106
109
  property = 'test'
107
110
  value = 'value'
108
111
  Twig.should_receive(:run).
109
- with(%{git config branch.#{branch}.#{property}}).
112
+ with(%{git config branch.#{@branch}.#{property}}).
110
113
  and_return(value)
111
114
 
112
- result = branch.get_property(property)
115
+ result = @branch.get_property(property)
113
116
  result.should == value
114
117
  end
118
+
119
+ it 'removes whitespace from branch property names' do
120
+ bad_property = ' foo foo '
121
+ property = 'foofoo'
122
+ value = 'bar'
123
+ Twig.should_receive(:run).
124
+ with(%{git config branch.#{@branch}.#{property}}).
125
+ and_return(value)
126
+
127
+ result = @branch.get_property(bad_property)
128
+ result.should == value
129
+ end
130
+
131
+ it 'returns nil if the property value is an empty string' do
132
+ property = 'test'
133
+ Twig.should_receive(:run).
134
+ with(%{git config branch.#{@branch}.#{property}}).
135
+ and_return('')
136
+
137
+ result = @branch.get_property(property)
138
+ result.should == nil
139
+ end
140
+
141
+ it 'raises an error if the property name is an empty string' do
142
+ property = ' '
143
+ Twig.should_not_receive(:run)
144
+
145
+ begin
146
+ @branch.get_property(property)
147
+ rescue Twig::Branch::EmptyPropertyNameError => exception
148
+ expected_exception = exception
149
+ end
150
+
151
+ expected_exception.message.should == Twig::Branch::EMPTY_PROPERTY_NAME_ERROR
152
+ end
115
153
  end
116
154
 
117
155
  describe '#set_property' do
@@ -133,33 +171,66 @@ describe Twig::Branch do
133
171
  )
134
172
  end
135
173
 
136
- it 'does nothing if Git cannot set the property value' do
174
+ it 'raises an error if Git cannot set the property value' do
137
175
  property = 'test'
138
176
  value = 'value'
139
177
  Twig.stub(:run) { `(exit 1)`; value } # Set `$?` to `1`
140
178
 
141
- result = @branch.set_property(property, value)
142
- result.should include(
179
+ begin
180
+ @branch.set_property(property, value)
181
+ rescue RuntimeError => exception
182
+ expected_exception = exception
183
+ end
184
+
185
+ expected_exception.message.should include(
143
186
  %{Could not save property "#{property}" as "#{value}" for branch "#{@branch}"}
144
187
  )
145
188
  end
146
189
 
147
- it 'returns an error if trying to set a reserved branch property' do
190
+ it 'raises an error if the property name is an empty string' do
191
+ property = ' '
192
+ value = 'value'
193
+ Twig.should_not_receive(:run)
194
+
195
+ begin
196
+ @branch.set_property(property, value)
197
+ rescue Twig::Branch::EmptyPropertyNameError => exception
198
+ expected_exception = exception
199
+ end
200
+
201
+ expected_exception.message.should == Twig::Branch::EMPTY_PROPERTY_NAME_ERROR
202
+ end
203
+
204
+ it 'raises an error if trying to set a reserved branch property' do
148
205
  property = 'merge'
149
206
  value = 'NOOO'
150
207
  Twig.should_not_receive(:run)
151
208
 
152
- result = @branch.set_property(property, value)
153
- result.should include(%{Can't modify the reserved property "#{property}"})
209
+ begin
210
+ @branch.set_property(property, value)
211
+ rescue ArgumentError => exception
212
+ expected_exception = exception
213
+ end
214
+
215
+ expected_exception.message.should include(
216
+ %{Can't modify the reserved property "#{property}"}
217
+ )
154
218
  end
155
219
 
156
- it 'returns an error if trying to set a branch property to an empty string' do
220
+ it 'raises an error if trying to set a branch property to an empty string' do
157
221
  property = 'test'
158
222
  value = ''
159
223
  Twig.should_not_receive(:run)
160
224
 
161
- result = @branch.set_property(property, value)
162
- result.should include(%{Can't set a branch property to an empty string})
225
+ begin
226
+ @branch.set_property(property, value)
227
+ rescue ArgumentError => exception
228
+ expected_exception = exception
229
+ end
230
+
231
+ expected_exception.message.should include(
232
+ %{Can't set a branch property to an empty string}
233
+ )
163
234
  end
164
235
 
165
236
  it 'removes whitespace from branch property names' do
@@ -225,12 +296,45 @@ describe Twig::Branch do
225
296
  )
226
297
  end
227
298
 
228
- it 'returns an error if the branch does not have the given property' do
229
- property = 'test'
230
- @branch.should_receive(:get_property).with(property).and_return('')
299
+ it 'removes whitespace from branch property names' do
300
+ bad_property = ' foo foo '
301
+ property = 'foofoo'
302
+ @branch.should_receive(:get_property).with(property).and_return('value')
303
+ Twig.should_receive(:run).
304
+ with(%{git config --unset branch.#{@branch}.#{property}})
231
305
 
232
- result = @branch.unset_property(property)
306
+ result = @branch.unset_property(bad_property)
233
307
  result.should include(
308
+ %{Removed property "#{property}" for branch "#{@branch}"}
309
+ )
310
+ end
311
+
312
+ it 'raises an error if the property name is an empty string' do
313
+ bad_property = ' '
314
+ property = ''
315
+ @branch.should_not_receive(:get_property)
316
+ Twig.should_not_receive(:run)
317
+
318
+ begin
319
+ @branch.unset_property(bad_property)
320
+ rescue Twig::Branch::EmptyPropertyNameError => exception
321
+ expected_exception = exception
322
+ end
323
+
324
+ expected_exception.message.should == Twig::Branch::EMPTY_PROPERTY_NAME_ERROR
325
+ end
326
+
327
+ it 'raises an error if the branch does not have the given property' do
328
+ property = 'test'
329
+ @branch.should_receive(:get_property).with(property).and_return(nil)
330
+
331
+ begin
332
+ @branch.unset_property(property)
333
+ rescue Twig::Branch::MissingPropertyError => exception
334
+ expected_exception = exception
335
+ end
336
+
337
+ expected_exception.message.should include(
234
338
  %{The branch "#{@branch}" does not have the property "#{property}"}
235
339
  )
236
340
  end
@@ -39,6 +39,26 @@ describe Twig::Cli do
39
39
  end
40
40
  end
41
41
 
42
+ describe '#help_paragraph' do
43
+ before :each do
44
+ @twig = Twig.new
45
+ end
46
+
47
+ it 'returns long text in a paragraph with line breaks' do
48
+ text = Array.new(5) {
49
+ 'The quick brown fox jumps over the lazy dog.'
50
+ }.join(' ')
51
+
52
+ result = @twig.help_paragraph(text)
53
+
54
+ result.should == [
55
+ "The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the",
56
+ "lazy dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps",
57
+ "over the lazy dog. The quick brown fox jumps over the lazy dog."
58
+ ].join("\n")
59
+ end
60
+ end
61
+
42
62
  describe '#read_cli_options!' do
43
63
  before :each do
44
64
  @twig = Twig.new
@@ -105,6 +125,14 @@ describe Twig::Cli do
105
125
  @twig.read_cli_options!(['--version'])
106
126
  end
107
127
 
128
+ it 'recognizes `--header-style`' do
129
+ @twig.options[:header_color].should == Twig::DEFAULT_HEADER_COLOR
130
+ @twig.options[:header_weight].should be_nil
131
+ @twig.read_cli_options!(['--header-style', 'green bold'])
132
+ @twig.options[:header_color].should == :green
133
+ @twig.options[:header_weight].should == :bold
134
+ end
135
+
108
136
  it 'handles invalid options' do
109
137
  @twig.should_receive(:puts) do |message|
110
138
  message.should include('invalid option: --foo')
@@ -201,7 +229,7 @@ describe Twig::Cli do
201
229
 
202
230
  it 'shows an error if getting a property that is not set' do
203
231
  @twig.should_receive(:get_branch_property).
204
- with(@branch_name, @property_name).and_return('')
232
+ with(@branch_name, @property_name).and_return(nil)
205
233
  @twig.should_receive(:abort) do |message|
206
234
  message.should include(
207
235
  %{The branch "#{@branch_name}" does not have the property "#{@property_name}"}
@@ -210,6 +238,18 @@ describe Twig::Cli do
210
238
 
211
239
  @twig.read_cli_args!([@property_name])
212
240
  end
241
+
242
+ it 'shows an error if getting a property whose name is an empty string' do
243
+ property_name = ' '
244
+ error_message = 'test error'
245
+ @twig.should_receive(:get_branch_property).
246
+ with(@branch_name, property_name) do
247
+ raise ArgumentError, error_message
248
+ end
249
+ @twig.should_receive(:abort).with(error_message)
250
+
251
+ @twig.read_cli_args!([property_name])
252
+ end
213
253
  end
214
254
 
215
255
  context 'with a specified branch' do
@@ -228,7 +268,7 @@ describe Twig::Cli do
228
268
 
229
269
  it 'shows an error if getting a property that is not set' do
230
270
  @twig.should_receive(:get_branch_property).
231
- with(@branch_name, @property_name).and_return('')
271
+ with(@branch_name, @property_name).and_return(nil)
232
272
  @twig.should_receive(:abort) do |message|
233
273
  message.should include(
234
274
  %{The branch "#{@branch_name}" does not have the property "#{@property_name}"}
@@ -269,6 +309,30 @@ describe Twig::Cli do
269
309
 
270
310
  @twig.read_cli_args!([@property_name, @property_value])
271
311
  end
312
+
313
+ it 'handles ArgumentError when setting an invalid branch property' do
314
+ error_message = 'test error'
315
+ @twig.should_receive(:current_branch_name).and_return(@branch_name)
316
+ @twig.should_receive(:set_branch_property).
317
+ with(@branch_name, @property_name, '') do
318
+ raise ArgumentError, error_message
319
+ end
320
+ @twig.should_receive(:abort).with(error_message)
321
+
322
+ @twig.read_cli_args!([@property_name, ''])
323
+ end
324
+
325
+ it 'handles RuntimeError when setting an invalid branch property' do
326
+ error_message = 'test error'
327
+ @twig.should_receive(:current_branch_name).and_return(@branch_name)
328
+ @twig.should_receive(:set_branch_property).
329
+ with(@branch_name, @property_name, '') do
330
+ raise RuntimeError, error_message
331
+ end
332
+ @twig.should_receive(:abort).with(error_message)
333
+
334
+ @twig.read_cli_args!([@property_name, ''])
335
+ end
272
336
  end
273
337
 
274
338
  context 'unsetting properties' do
@@ -297,6 +361,30 @@ describe Twig::Cli do
297
361
 
298
362
  @twig.read_cli_args!([])
299
363
  end
364
+
365
+ it 'handles ArgumentError when unsetting an invalid branch property' do
366
+ error_message = 'test error'
367
+ @twig.should_receive(:current_branch_name).and_return(@branch_name)
368
+ @twig.should_receive(:unset_branch_property).
369
+ with(@branch_name, @property_name) do
370
+ raise ArgumentError, error_message
371
+ end
372
+ @twig.should_receive(:abort).with(error_message)
373
+
374
+ @twig.read_cli_args!([])
375
+ end
376
+
377
+ it 'handles MissingPropertyError when unsetting a missing branch property' do
378
+ error_message = 'test error'
379
+ @twig.should_receive(:current_branch_name).and_return(@branch_name)
380
+ @twig.should_receive(:unset_branch_property).
381
+ with(@branch_name, @property_name) do
382
+ raise Twig::Branch::MissingPropertyError, error_message
383
+ end
384
+ @twig.should_receive(:abort).with(error_message)
385
+
386
+ @twig.read_cli_args!([])
387
+ end
300
388
  end
301
389
  end
302
390
 
@@ -36,9 +36,11 @@ describe Twig::Display do
36
36
  end
37
37
 
38
38
  describe '#branch_list_headers' do
39
- it 'returns a string of branch properties and underlines' do
39
+ before :each do
40
40
  Twig::Branch.stub(:all_properties => %w[foo quux])
41
+ end
41
42
 
43
+ it 'returns a string of branch properties and underlines' do
42
44
  result = @twig.branch_list_headers({})
43
45
  result_lines = result.split("\n")
44
46
 
@@ -54,6 +56,36 @@ describe Twig::Display do
54
56
  '---- ' + (' ' * column_width) +
55
57
  ' ------' + (' ' * column_width)
56
58
  end
59
+
60
+ it 'sets a header color' do
61
+ result = @twig.branch_list_headers({ :header_color => :green })
62
+ header_line = result.split("\n").first
63
+ color = Twig::Display::COLORS[:green]
64
+ header_line.gsub(/\s/, '').should ==
65
+ "\e[#{color}mfoo\e[0m" <<
66
+ "\e[#{color}mquux\e[0m" <<
67
+ "\e[#{color}mbranch\e[0m"
68
+ end
69
+
70
+ it 'sets a header weight' do
71
+ result = @twig.branch_list_headers({ :header_weight => :bold })
72
+ header_line = result.split("\n").first
73
+ weight = Twig::Display::WEIGHTS[:bold]
74
+ header_line.gsub(/\s/, '').should ==
75
+ "\e[#{weight}mfoo\e[0m" <<
76
+ "\e[#{weight}mquux\e[0m" <<
77
+ "\e[#{weight}mbranch\e[0m"
78
+ end
79
+
80
+ it 'sets a header color and weight' do
81
+ result = @twig.branch_list_headers({ :header_color => :red, :header_weight => :bold })
82
+ header_line = result.split("\n").first
83
+ color, weight = Twig::Display::COLORS[:red], Twig::Display::WEIGHTS[:bold]
84
+ header_line.gsub(/\s/, '').should ==
85
+ "\e[#{color};#{weight}mfoo\e[0m" <<
86
+ "\e[#{color};#{weight}mquux\e[0m" <<
87
+ "\e[#{color};#{weight}mbranch\e[0m"
88
+ end
57
89
  end
58
90
 
59
91
  describe '#branch_list_line' do
@@ -90,6 +122,19 @@ describe Twig::Display do
90
122
  result.should =~ /2000-01-01\s+foo!\s+bar!\s+#{Regexp.escape(branch.name)}/
91
123
  end
92
124
 
125
+ it 'returns a line containing an empty branch property' do
126
+ Twig::Branch.stub(:all_properties => %w[foo bar baz])
127
+ @twig.should_receive(:get_branch_property).
128
+ with(anything, 'baz').and_return(nil)
129
+ branch = Twig::Branch.new('other-branch')
130
+ branch.should_receive(:last_commit_time).and_return(@commit_time)
131
+
132
+ result = @twig.branch_list_line(branch)
133
+
134
+ empty_indicator = Twig::Display::EMPTY_BRANCH_PROPERTY_INDICATOR
135
+ result.should =~ /2000-01-01\s+foo!\s+bar!\s+#{empty_indicator}\s+#{Regexp.escape(branch.name)}/
136
+ end
137
+
93
138
  it 'changes line break characters to spaces' do
94
139
  branch = Twig::Branch.new('my-branch')
95
140
  branch.should_receive(:last_commit_time).and_return(@commit_time)
@@ -110,12 +155,12 @@ describe Twig::Display do
110
155
 
111
156
  it 'returns a string with a color code' do
112
157
  @twig.format_string('foo', :color => :red).
113
- should == "\033[#{Twig::Display::COLORS[:red]}mfoo\033[0m"
158
+ should == "\e[#{Twig::Display::COLORS[:red]}mfoo\e[0m"
114
159
  end
115
160
 
116
161
  it 'returns a string with a weight code' do
117
162
  @twig.format_string('foo', :weight => :bold).
118
- should == "\033[#{Twig::Display::WEIGHTS[:bold]}mfoo\033[0m"
163
+ should == "\e[#{Twig::Display::WEIGHTS[:bold]}mfoo\e[0m"
119
164
  end
120
165
 
121
166
  it 'returns a string with a color and weight code 'do
@@ -123,7 +168,34 @@ describe Twig::Display do
123
168
  weight_code = Twig::Display::WEIGHTS[:bold]
124
169
 
125
170
  @twig.format_string('foo', :color => :red, :weight => :bold).
126
- should == "\033[#{color_code};#{weight_code}mfoo\033[0m"
171
+ should == "\e[#{color_code};#{weight_code}mfoo\e[0m"
172
+ end
173
+ end
174
+
175
+ describe '#formatted_string_display_size' do
176
+ it 'returns the width of a plain text string' do
177
+ @twig.formatted_string_display_size('foo').should == 3
178
+ end
179
+
180
+ it 'returns the width of a string with color' do
181
+ string = @twig.format_string('foo', :color => :red)
182
+ string.size.should > 3 # Precondition
183
+
184
+ @twig.formatted_string_display_size(string).should == 3
185
+ end
186
+
187
+ it 'returns the width of a string with weight' do
188
+ string = @twig.format_string('foo', :weight => :bold)
189
+ string.size.should > 3 # Precondition
190
+
191
+ @twig.formatted_string_display_size(string).should == 3
192
+ end
193
+
194
+ it 'returns the width of a string with color and weight' do
195
+ string = @twig.format_string('foo', :color => :red, :weight => :bold)
196
+ string.size.should > 3 # Precondition
197
+
198
+ @twig.formatted_string_display_size(string).should == 3
127
199
  end
128
200
  end
129
201
  end