letters 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,13 +1,7 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
 
3
3
  gem "awesome_print"
4
4
  gem "activesupport"
5
5
  gem "xml-simple"
6
6
  gem "timecop"
7
7
  gem "colorize"
8
-
9
- if RUBY_VERSION =~ /1\.9\.\d+/
10
- gem "debugger"
11
- else
12
- gem "ruby-debug"
13
- end
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  **Letters** is a little alphabetical library that makes sophisticated debugging easy & fun.
2
2
 
3
- *Quick note about Rails*: Until I build a Rails-specific gem, I'm changing Letters to patch `Object` by default. To only patch core classes, `require "letters/patch/core"`. For Rails support, `require "letters/patch/rails"`. Make sure to do this after `Bundler.require` in `application.rb`.
3
+ *Quick note about Rails*: Until I build a Rails-specific gem, I'm changing Letters to patch `Object` by default. To only patch core classes, `require "letters/patch/core"`. For Rails support, `require "letters/patch/rails"`. Make sure to do this after `Bundler.require` in `application.rb`.
4
4
 
5
5
  For many of us, troubleshooting begins and ends with the `print` statement. Others recruit the debugger, too. (Maybe you use `print` statements to look at changes over time but the debugger to focus on a small bit of code.) These tools are good, but they are the lowest level of how we can debug in Ruby. Letters leverages `print`, the debugger, control transfer, computer beeps, and other side-effects for more well-rounded visibility into code and state.
6
6
 
@@ -21,7 +21,7 @@ There are almost 20 Letters methods so far. You can find them [in the documentat
21
21
  Let's use with the `o` method as an example. It is one of the most familiar methods. Calling it prints the receiver to STDOUT and returns the receiver:
22
22
 
23
23
  ```ruby
24
- { foo: "bar" }.o
24
+ { foo: "bar" }.o
25
25
  # => { foo: "bar" }
26
26
  # prints { foo: "bar" }
27
27
  ```
@@ -35,7 +35,7 @@ words.grep(/interesting/).
35
35
  values_at(5, 10).
36
36
  slice(0..2).
37
37
  join(", ")
38
- ```
38
+ ```
39
39
 
40
40
  If I want to know the state of your code after lines 3 and 5, all I have to do is add `.o` to each one:
41
41
 
@@ -55,6 +55,14 @@ This is significantly easier than breaking apart the pipeline using variable ass
55
55
  The `o` method takes options, too, so you can add a prefix message to the output or choose another output format -- like [YAML]() or [pretty print]().
56
56
 
57
57
  ### The methods ###
58
+
59
+ Here are the methods, listed with any options that can be passed in to modify their behavior. Some options are available to all methods and are not listed in the table below:
60
+
61
+ - `:message (string)`: Print out the specified message as the method is being called.
62
+ - `:line_no (boolean)`: Print out the line number where a method is called as it is being called
63
+
64
+ You can easily set these for an entire project using global configuration if you wish (see below).
65
+
58
66
  <table>
59
67
  <tr>
60
68
  <th>Letter</th>
@@ -64,246 +72,115 @@ The `o` method takes options, too, so you can add a prefix message to the output
64
72
  </tr>
65
73
 
66
74
  <tr>
67
- <td>
68
- <a href="http://lettersrb.com/api#a">a</a>
69
- </td>
70
- <td>
71
- Assert
72
- </td>
73
- <td>
74
- :message,
75
- :error_class
76
- </td>
77
- <td>
78
- asserts in the context of its receiver or Letters::AssertionError
79
- </td>
75
+ <td><a href="http://lettersrb.com/api#a">a</a></td>
76
+ <td>Assert</td>
77
+ <td><code>:error_class</code></td>
78
+ <td>asserts in the context of its receiver or <code>Letters::AssertionError</code></td>
80
79
  </tr>
81
80
 
82
81
  <tr>
83
- <td>
84
- <a href="http://lettersrb.com/api#b">b</a>
85
- </td>
86
- <td>
87
- Beep
88
- </td>
89
- <td>
90
- </td>
91
- <td>
92
- causes your terminal to beep
93
- </td>
82
+ <td><a href="http://lettersrb.com/api#b">b</a></td>
83
+ <td>Beep</td>
84
+ <td></td>
85
+ <td>causes your terminal to beep</td>
94
86
  </tr>
95
87
 
96
88
  <tr>
97
- <td>
98
- <a href="http://lettersrb.com/api#c">c</a>
99
- </td>
100
- <td>
101
- Callstack
102
- </td>
103
- <td>
104
- :message
105
- </td>
106
- <td>
107
- prints the current callstack
108
- </td>
89
+ <td><a href="http://lettersrb.com/api#c">c</a></td>
90
+ <td>Callstack</td>
91
+ <td></td>
92
+ <td>prints the current callstack</td>
109
93
  </tr>
110
94
 
111
95
  <tr>
112
- <td>
113
- <a href="http://lettersrb.com/api#d">d</a>
114
- </td>
115
- <td>
116
- Debugger
117
- </td>
118
- <td>
119
-
120
- </td>
121
- <td>
122
- passes control to the debugger
123
- </td>
96
+ <td><a href="http://lettersrb.com/api#d">d</a></td>
97
+ <td>Debugger</td>
98
+ <td></td>
99
+ <td>passes control to the debugger</td>
124
100
  </tr>
125
101
 
126
102
  <tr>
127
- <td>
128
- <a href="http://lettersrb.com/api#d1/d2">d1/d2</a>
129
- </td>
130
- <td>
131
- Diff
132
- </td>
133
- <td>
134
- :message,
135
- :format,
136
- :stream
137
- </td>
138
- <td>
139
- prints a diff between first and second receivers
140
- </td>
103
+ <td><a href="http://lettersrb.com/api#d1/d2">d1/d2</a></td>
104
+ <td>Diff</td>
105
+ <td><code>:format</code>,<code>:stream</code></td>
106
+ <td>prints a diff between first and second receivers</td>
141
107
  </tr>
142
108
 
143
109
  <tr>
144
- <td>
145
- <a href="http://lettersrb.com/api#e">e</a>
146
- </td>
147
- <td>
148
- Empty
149
- </td>
150
- <td>
151
- :message
152
- </td>
153
- <td>
154
- raises a Letters::EmptyError if its receiver is empty
155
- </td>
110
+ <td><a href="http://lettersrb.com/api#e">e</a></td>
111
+ <td>Empty</td>
112
+ <td></td>
113
+ <td>raises a <code>Letters::EmptyError</code> if its receiver is empty</td>
156
114
  </tr>
157
115
 
158
116
  <tr>
159
- <td>
160
- <a href="http://lettersrb.com/api#f">f</a>
161
- </td>
162
- <td>
163
- File
164
- </td>
165
- <td>
166
- :format, :name
167
- </td>
168
- <td>
169
- writes its receiver into a file in a given format
170
- </td>
117
+ <td><a href="http://lettersrb.com/api#f">f</a></td>
118
+ <td>File</td>
119
+ <td><code>:format</code>, <code>:name</code></td>
120
+ <td>writes its receiver into a file in a given format</td>
171
121
  </tr>
172
122
 
173
123
  <tr>
174
- <td>
175
- <a href="http://lettersrb.com/api#j">j</a>
176
- </td>
177
- <td>
178
- Jump
179
- </td>
180
- <td>
181
- (&block)
182
- </td>
183
- <td>
184
- executes its block in the context of its receiver
185
- </td>
124
+ <td><a href="http://lettersrb.com/api#j">j</a></td>
125
+ <td>Jump</td>
126
+ <td>(<code>&block</code>)</td>
127
+ <td>executes its block in the context of its receiver</td>
186
128
  </tr>
187
129
 
188
130
  <tr>
189
- <td>
190
- <a href="http://lettersrb.com/api#k">k</a>
191
- </td>
192
- <td>
193
- Kill
194
- </td>
195
- <td>
196
- :on
197
- </td>
198
- <td>
199
- raises Letters::KillError at a specified number of calls
200
- </td>
131
+ <td><a href="http://lettersrb.com/api#k">k</a></td>
132
+ <td>Kill</td>
133
+ <td><code>:on</code></td>
134
+ <td>raises <code>Letters::KillError</code> at a specified number of calls</td>
201
135
  </tr>
202
136
 
203
137
  <tr>
204
- <td>
205
- <a href="http://lettersrb.com/api#l">l</a>
206
- </td>
207
- <td>
208
- Logger
209
- </td>
210
- <td>
211
- :format, :level
212
- </td>
213
- <td>
214
- logs its receivers on the available logger instance
215
- </td>
138
+ <td><a href="http://lettersrb.com/api#l">l</a></td>
139
+ <td>Logger</td>
140
+ <td><code>:format</code>, <code>:level</code></td>
141
+ <td>logs its receivers on the available logger instance</td>
216
142
  </tr>
217
143
 
218
144
  <tr>
219
- <td>
220
- <a href="http://lettersrb.com/api#m">m</a>
221
- </td>
222
- <td>
223
- Mark as tainted
224
- </td>
225
- <td>
226
- (true|false)
227
- </td>
228
- <td>
229
- taints (or untaints) its receiver
230
- </td>
145
+ <td><a href="http://lettersrb.com/api#m">m</a></td>
146
+ <td>Mark as tainted</td>
147
+ <td>(<code>true</code>|<code>false</code>)</td>
148
+ <td>taints (or untaints) its receiver</td>
231
149
  </tr>
232
150
 
233
151
  <tr>
234
- <td>
235
- <a href="http://lettersrb.com/api#n">n</a>
236
- </td>
237
- <td>
238
- Nil
239
- </td>
240
- <td>
241
-
242
- </td>
243
- <td>
244
- raises a Letters::NilError if its receiver is nil
245
- </td>
152
+ <td><a href="http://lettersrb.com/api#n">n</a></td>
153
+ <td>Nil</td>
154
+ <td></td>
155
+ <td>raises a <code>Letters::NilError</code> if its receiver is nil</td>
246
156
  </tr>
247
157
 
248
158
  <tr>
249
- <td>
250
- <a href="http://lettersrb.com/api#o">o</a>
251
- </td>
252
- <td>
253
- Output
254
- </td>
255
- <td>
256
- :format,
257
- :stream
258
- </td>
259
- <td>
260
- prints its receiver to standard output
261
- </td>
159
+ <td><a href="http://lettersrb.com/api#o">o</a></td>
160
+ <td>Output</td>
161
+ <td><code>:format</code>, <code>:stream</code></td>
162
+ <td>prints its receiver to standard output</td>
262
163
  </tr>
263
164
 
264
165
  <tr>
265
- <td>
266
- <a href="http://lettersrb.com/api#r">r</a>
267
- </td>
268
- <td>
269
- Ri
270
- </td>
271
- <td>
272
- (method name as symbol)
273
- </td>
274
- <td>
275
- prints RI documentation of its receiver class
276
- </td>
166
+ <td><a href="http://lettersrb.com/api#r">r</a></td>
167
+ <td>Ri</td>
168
+ <td>(method name as symbol)</td>
169
+ <td>prints RI documentation of its receiver class</td>
277
170
  </tr>
278
171
 
279
172
  <tr>
280
- <td>
281
- <a href="http://lettersrb.com/api#s">s</a>
282
- </td>
283
- <td>
284
- Safety
285
- </td>
286
- <td>
287
- (level number)
288
- </td>
289
- <td>
290
- bumps the safety level (by one or as specified)
291
- </td>
173
+ <td><a href="http://lettersrb.com/api#s">s</a></td>
174
+ <td>Safety</td>
175
+ <td>(level number)</td>
176
+ <td>bumps the safety level (by one or as specified)</td>
292
177
  </tr>
293
178
 
294
179
  <tr>
295
- <td>
296
- <a href="http://lettersrb.com/api#t">t</a>
297
- </td>
298
- <td>
299
- Timestamp
300
- </td>
301
- <td>
302
- :time_format
303
- </td>
304
- <td>
305
- prints out the current timestamp
306
- </td>
180
+ <td><a href="http://lettersrb.com/api#t">t</a></td>
181
+ <td>Timestamp</td>
182
+ <td><code>:time_format</code></td>
183
+ <td>prints out the current timestamp</td>
307
184
  </tr>
308
185
  </table>
309
186
 
@@ -318,3 +195,11 @@ Letters.config do
318
195
  f :format => "pp", :name => "my-special-file"
319
196
  end
320
197
  ```
198
+
199
+ You can also change options globally, for methods where the global option is appropriate. For example, if you want every Letters method to print out its line number when called, you can do this for all methods at once:
200
+
201
+ ```ruby
202
+ Letters.config do
203
+ all :line_no => true
204
+ end
205
+ ```
@@ -18,15 +18,24 @@ module Letters
18
18
  end
19
19
  end
20
20
 
21
+ def self.global_defaults=(opts)
22
+ @global_defaults = opts
23
+ end
24
+
25
+ def self.global_defaults
26
+ @global_defaults || {}
27
+ end
28
+
21
29
  def self.user_defaults
22
30
  @user_defaults ||= Hash.new {|h, k| h[k] = Hash.new }
23
31
  end
24
32
 
25
33
  def self.defaults_with(letter, opts={})
26
- defaults[letter].merge(user_defaults[letter]).merge(opts)
34
+ [global_defaults, defaults[letter], user_defaults[letter], opts].reduce({}, &:merge)
27
35
  end
28
36
 
29
37
  def self.reset_config!
38
+ global_defaults.clear
30
39
  user_defaults.clear
31
40
  end
32
41
 
@@ -35,6 +44,10 @@ module Letters
35
44
  end
36
45
 
37
46
  module Config
47
+ define_singleton_method("all") do |opts={}|
48
+ Letters.global_defaults = opts
49
+ end
50
+
38
51
  ("a".."z").each do |letter|
39
52
  define_singleton_method(letter) do |opts={}|
40
53
  Letters.user_defaults[letter.to_sym] = opts
@@ -7,107 +7,109 @@ require "letters/empty_error"
7
7
  require "letters/kill_error"
8
8
  require "letters/nil_error"
9
9
 
10
+ require "colorize"
11
+
10
12
  module Letters
11
13
  module CoreExt
12
14
  DELIM = "-" * 20
13
15
 
16
+ def ubertap(letter, opts={}, orig_caller=[], &block)
17
+ full_opts = Letters.defaults_with(letter, opts)
18
+ Helpers.message full_opts
19
+ Helpers.print_line(orig_caller[0]) if full_opts[:line_no]
20
+
21
+ tap do |o|
22
+ block.call(o, full_opts)
23
+ end
24
+ end
25
+
14
26
  # Assert
15
27
  def a(opts={}, &block)
16
- opts = Letters.defaults_with(:a, opts)
17
- tap do |o|
18
- Helpers.message opts
28
+ ubertap(:a, opts, caller) do |o, full_opts|
19
29
  if block_given? && !o.instance_eval(&block)
20
- raise opts[:error_class]
30
+ raise full_opts[:error_class]
21
31
  end
22
32
  end
23
33
  end
24
34
 
25
35
  # Beep
26
- def b
27
- tap do
36
+ def b(opts={})
37
+ ubertap(:b, opts, caller) do |_, _|
28
38
  $stdout.print "\a"
29
39
  end
30
40
  end
31
41
 
32
42
  # Callstack
33
43
  def c(opts={})
34
- tap do
35
- Helpers.message opts
36
- Helpers.out caller(4), opts
44
+ ubertap(:b, opts, caller) do |_, full_opts|
45
+ Helpers.out caller(4), full_opts
37
46
  end
38
47
  end
39
48
 
40
49
  # Debug
41
- def d
42
- tap do
43
- Helpers.call_debugger
50
+ def d(opts={})
51
+ ubertap(:d, opts, caller) do |_, _|
52
+ Helpers.call_debugger
44
53
  end
45
54
  end
46
55
 
47
56
  # Diff 1
48
- def d1
49
- tap do |o|
57
+ def d1(opts={})
58
+ ubertap(:d1, opts, caller) do |o, _|
50
59
  Letters.object_for_diff = o
51
60
  end
52
61
  end
53
62
 
54
63
  # Diff 2
55
64
  def d2(opts={})
56
- opts = Letters.defaults_with(:d2, opts)
57
- tap do |o|
65
+ ubertap(:d2, opts, caller) do |o, full_opts|
58
66
  diff = Helpers.diff(Letters.object_for_diff, o)
59
- Helpers.message opts
60
- Helpers.out diff, opts
67
+ Helpers.out diff, full_opts
61
68
  Letters.object_for_diff = nil
62
69
  end
63
70
  end
64
-
71
+
65
72
  # Empty check
66
73
  def e(opts={})
67
74
  opts.merge! :error_class => EmptyError
68
- tap do |o|
69
- Helpers.message opts
70
- o.a(opts) { !empty? }
75
+ ubertap(:e, opts, caller) do |o, full_opts|
76
+ o.a(full_opts) { !empty? }
71
77
  end
72
78
  end
73
79
 
74
80
  # File
75
81
  def f(opts={})
76
- opts = Letters.defaults_with(:f, opts)
77
- tap do |o|
82
+ ubertap(:f, opts, caller) do |o, full_opts|
78
83
  suffixes = [""] + (1..50).to_a
79
- deduper = suffixes.detect {|x| !File.directory? "#{opts[:name]}#{x}" }
84
+ deduper = suffixes.detect {|x| !File.directory? "#{full_opts[:name]}#{x}" }
80
85
 
81
- File.open("#{opts[:name]}#{deduper}", "w+") do |file|
86
+ File.open("#{full_opts[:name]}#{deduper}", "w+") do |file|
82
87
  # Override :stream
83
- opts.merge! :stream => file
84
- Helpers.message opts
85
- Helpers.out o, opts
88
+ full_opts.merge! :stream => file
89
+ Helpers.out o, full_opts
86
90
  end
87
91
  end
88
92
  end
89
93
 
90
94
  # Jump
91
- def j(&block)
92
- tap do |o|
95
+ def j(opts={}, &block)
96
+ ubertap(:j, opts, caller) do |o, full_opts|
93
97
  o.instance_eval &block
94
98
  end
95
99
  end
96
100
 
97
101
  # Kill
98
102
  def k(opts={})
99
- opts = Letters.defaults_with(:k, opts)
100
-
101
- # Support :max option until I can deprecate it
102
- opts[:on] ||= opts[:max]
103
-
104
103
  opts.merge! :error_class => KillError
105
- tap do |o|
104
+ ubertap(:k, opts, caller) do |o, full_opts|
105
+ # Support :max option until I can deprecate it
106
+ full_opts[:on] ||= full_opts[:max]
107
+
106
108
  Letters.kill_count ||= 0
107
109
 
108
- if Letters.kill_count >= opts[:on]
110
+ if Letters.kill_count >= full_opts[:on]
109
111
  Letters.kill_count = 0
110
- o.a(opts) { false }
112
+ o.a(full_opts) { false }
111
113
  end
112
114
 
113
115
  Letters.kill_count += 1
@@ -116,11 +118,10 @@ module Letters
116
118
 
117
119
  # Log
118
120
  def l(opts={})
119
- opts = Letters.defaults_with(:l, opts)
120
- tap do |o|
121
+ ubertap(:l, opts, caller) do |o, full_opts|
121
122
  begin
122
- logger.send(opts[:level], opts[:message]) if opts[:message]
123
- logger.send(opts[:level], Helpers.send(opts[:format], o))
123
+ logger.send(full_opts[:level], full_opts[:message]) if full_opts[:message]
124
+ logger.send(full_opts[:level], Helpers.send(full_opts[:format], o))
124
125
  rescue
125
126
  $stdout.puts "[warning] No logger available"
126
127
  end
@@ -128,8 +129,8 @@ module Letters
128
129
  end
129
130
 
130
131
  # Taint and untaint object
131
- def m(taint=true)
132
- tap do |o|
132
+ def m(taint=true, opts={})
133
+ ubertap(:m, opts, caller) do |o, _|
133
134
  if taint
134
135
  o.taint
135
136
  else
@@ -141,32 +142,31 @@ module Letters
141
142
  # Nil check
142
143
  def n(opts={})
143
144
  opts.merge! :error_class => NilError
144
- tap do |o|
145
- o.a(opts) { !nil? }
145
+ ubertap(:n, opts, caller) do |o, full_opts|
146
+ o.a(full_opts) { !nil? }
146
147
  end
147
148
  end
148
149
 
149
150
  # Print to STDOUT
150
151
  def o(opts={}, &block)
151
- opts = Letters.defaults_with(:o, opts)
152
- tap do |o|
153
- Helpers.message opts
154
- obj = block_given? ? o.instance_eval(&block) : o
155
- Helpers.out obj, opts
152
+ ubertap(:o, opts, caller) do |o, full_opts|
153
+ Helpers.message full_opts
154
+ obj = block_given? ? o.instance_eval(&block) : o
155
+ Helpers.out obj, full_opts
156
156
  end
157
157
  end
158
158
 
159
159
  # RI
160
- def r(method=nil)
161
- tap do |o|
160
+ def r(method=nil, opts={})
161
+ ubertap(:r, opts, caller) do |o, _|
162
162
  method_or_empty = method ? "##{method}" : method
163
- system "ri #{o.class}#{method_or_empty}"
163
+ system "ri #{o.class}#{method_or_empty}"
164
164
  end
165
165
  end
166
166
 
167
167
  # Change safety level
168
- def s(level=nil)
169
- tap do
168
+ def s(level=nil, opts={})
169
+ ubertap(:s, opts) do |_, _|
170
170
  level ||= $SAFE + 1
171
171
  Helpers.change_safety level
172
172
  end
@@ -174,10 +174,8 @@ module Letters
174
174
 
175
175
  # Timestamp
176
176
  def t(opts={})
177
- opts = Letters.defaults_with(:t, opts)
178
- tap do
179
- Helpers.message opts
180
- Helpers.out Time.now.to_s(opts[:time_format].to_sym), opts
177
+ ubertap(:t, opts) do |_, full_opts|
178
+ Helpers.out Time.now.to_s(full_opts[:time_format].to_sym), full_opts
181
179
  end
182
180
  end
183
181
  end
@@ -1,4 +1,5 @@
1
1
  require "colorize"
2
+ require "pathname"
2
3
 
3
4
  module Letters
4
5
  module Helpers
@@ -13,13 +14,13 @@ module Letters
13
14
  when String
14
15
  diff(obj1.split("\n"), obj2.split("\n"))
15
16
  else
16
- {
17
+ {
17
18
  removed: Array(obj1 - obj2),
18
19
  added: Array(obj2 - obj1)
19
20
  }
20
21
  end
21
22
  rescue
22
- raise "cannot diff the two marked objects"
23
+ raise "cannot diff the two marked objects"
23
24
  end
24
25
 
25
26
  def self.message(opts={})
@@ -60,6 +61,23 @@ module Letters
60
61
  object.to_yaml
61
62
  end
62
63
 
64
+ def self.print_line(caller_line)
65
+ file, line_no = caller_line.split.first.sub(/:in$/, "").split(":")
66
+
67
+ line = if File.exist?(file) && File.file?(file)
68
+ File.readlines(file)[Integer(line_no) - 1]
69
+ else
70
+ ""
71
+ end
72
+
73
+ rel_file = Pathname.new(file).expand_path.relative_path_from(Pathname.getwd)
74
+
75
+ puts "Letters call at #{file}, line #{line_no}".underline
76
+ puts
77
+ puts " " + line.strip.chomp.sub(/^\W*/, "").green
78
+ puts
79
+ end
80
+
63
81
  def self.pretty_callstack(callstack)
64
82
  home = ENV["MY_RUBY_HOME"]
65
83
 
@@ -81,12 +99,12 @@ module Letters
81
99
 
82
100
  parsed.unshift headers
83
101
 
84
- longest_line =
102
+ longest_line =
85
103
  parsed.map {|entry| entry[:line] }.
86
104
  sort_by(&:length).
87
105
  last
88
106
 
89
- longest_method =
107
+ longest_method =
90
108
  parsed.map {|entry| entry[:method_name] }.
91
109
  sort_by(&:length).
92
110
  last
@@ -98,8 +116,13 @@ module Letters
98
116
 
99
117
  # This provides a mockable method for testing
100
118
  def self.call_debugger
101
- require "ruby-debug"
102
- debugger
119
+ if (defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx')
120
+ require 'rubinius/debugger'
121
+ Rubinius::Debugger.start
122
+ else
123
+ require 'debug'
124
+ end
125
+
103
126
  nil
104
127
  end
105
128
 
@@ -1,3 +1,3 @@
1
1
  module Letters
2
- VERSION = "0.3.1"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -12,7 +12,8 @@ module Letters
12
12
  end
13
13
 
14
14
  after do
15
- FileUtils.rm "log"
15
+ Letters.reset_config!
16
+ FileUtils.rm_rf "log"
16
17
  end
17
18
 
18
19
  describe ".config" do
@@ -20,6 +21,25 @@ module Letters
20
21
  hash.f
21
22
  File.read("log").should == hash.pretty_inspect
22
23
  end
24
+
25
+ it "allows global default argument configuration" do
26
+ Letters.config do
27
+ all :line_no => true
28
+ end
29
+
30
+ $stdout.should_receive(:puts).exactly(4).times
31
+ hash.b
32
+ end
33
+
34
+ it "allows specific defaults to override global defaults" do
35
+ Letters.config do
36
+ all :line_no => true
37
+ b :line_no => false
38
+ end
39
+
40
+ $stdout.should_receive(:puts).never
41
+ hash.b
42
+ end
23
43
  end
24
44
 
25
45
  describe ".reset_config!" do
@@ -35,6 +35,11 @@ module Letters
35
35
  hash.o { nil }.should == hash
36
36
  end
37
37
 
38
+ it "all letter methods have the option of outputting the line where they are called" do
39
+ pending "I need to figure out a good way to test this"
40
+ # hash.j(:line_no => true) { nil }.should == hash
41
+ end
42
+
38
43
  describe "#a (assert)" do
39
44
  it "jumps into the receiver's calling context" do
40
45
  lambda do
@@ -44,7 +49,7 @@ module Letters
44
49
 
45
50
  it "raises a Letters::AssertionError if the block returns false" do
46
51
  lambda do
47
- [1, 2, 3].a { count > 3 }
52
+ [1, 2, 3].a { count > 3 }
48
53
  end.should raise_error(Letters::AssertionError)
49
54
  end
50
55
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: letters
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-07 00:00:00.000000000 Z
12
+ date: 2013-07-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: awesome_print
16
- requirement: &70186112051180 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70186112051180
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: activesupport
27
- requirement: &70186112050660 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ! '>='
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: '0'
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70186112050660
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: xml-simple
38
- requirement: &70186112050040 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: '0'
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *70186112050040
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: colorize
49
- requirement: &70186112049280 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,21 +69,15 @@ dependencies:
54
69
  version: '0'
55
70
  type: :runtime
56
71
  prerelease: false
57
- version_requirements: *70186112049280
58
- - !ruby/object:Gem::Dependency
59
- name: debugger
60
- requirement: &70186112048660 !ruby/object:Gem::Requirement
72
+ version_requirements: !ruby/object:Gem::Requirement
61
73
  none: false
62
74
  requirements:
63
75
  - - ! '>='
64
76
  - !ruby/object:Gem::Version
65
77
  version: '0'
66
- type: :runtime
67
- prerelease: false
68
- version_requirements: *70186112048660
69
78
  - !ruby/object:Gem::Dependency
70
79
  name: timecop
71
- requirement: &70186112048240 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
72
81
  none: false
73
82
  requirements:
74
83
  - - ! '>='
@@ -76,10 +85,15 @@ dependencies:
76
85
  version: '0'
77
86
  type: :development
78
87
  prerelease: false
79
- version_requirements: *70186112048240
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
80
94
  - !ruby/object:Gem::Dependency
81
95
  name: rspec
82
- requirement: &70186112047760 !ruby/object:Gem::Requirement
96
+ requirement: !ruby/object:Gem::Requirement
83
97
  none: false
84
98
  requirements:
85
99
  - - ! '>='
@@ -87,7 +101,12 @@ dependencies:
87
101
  version: '0'
88
102
  type: :development
89
103
  prerelease: false
90
- version_requirements: *70186112047760
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
91
110
  description: Letters brings Ruby debugging into the 21st century. It leverages print,
92
111
  the debugger, control transfer, even computer beeps to let you see into your code's
93
112
  state.
@@ -143,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
162
  version: 1.3.6
144
163
  requirements: []
145
164
  rubyforge_project:
146
- rubygems_version: 1.8.15
165
+ rubygems_version: 1.8.23
147
166
  signing_key:
148
167
  specification_version: 3
149
168
  summary: A tiny debugging library for Ruby