im-lost 1.0.0 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39160aff2b7fa8320ae12c5d035fa40fbf6f96a2fbe0418ddfb31ac700c2bf72
4
- data.tar.gz: 044bf4b9b4f9288f418b0cc5344cc82d1a88839d08a8ef1b8008d616ef11481c
3
+ metadata.gz: 8b3508c022462842507ce749828e2c74c4db9e9097496e68cedc758018017cb5
4
+ data.tar.gz: 93ac54d98ae6474d4f7144b116cf0e2784c88babf57ff592a317b463caa7ee13
5
5
  SHA512:
6
- metadata.gz: 5d76261aafb61289cf56c23fb2acb0c0e6a0b8cc834b4e28b72d80cf0f6dfdf7966a8b613c7a0f4e8ee005eae2ba4064fe9aeb7b7520cbd53ce8e99671e33f0f
7
- data.tar.gz: da598803cf6e2ee4e4baa92f8e702796050f279645daf80fccffa16c2be2eaa314cee7a69742691dde5d798f44f75d610dcb7db71d223a72c0fcabb2e65c7030
6
+ metadata.gz: 4d45f27c98a6ed477ce4e696f4c41286ca24c105de1668889bf64fc0d57d3947e04c026b40fa7f5f79e2ce5016fcc8327e3c9a8b20a1e6ae0561900efae4f5f3
7
+ data.tar.gz: 1502147a826924c39988f9272d62e3c0274dc8cdb961f25c405a229cf6273142579ad136af1972c06874d13af110486b79db45907c219bd3082a91cd507220ab
data/README.md CHANGED
@@ -20,14 +20,14 @@ File.open('test.txt', 'w') do |file|
20
20
  end
21
21
  end
22
22
  # output will look like
23
- # > IO#<<(?)
24
- # /projects/test.rb:1
25
- # > IO#write(*)
26
- # /projects/test.rb:1
27
- # > IO#puts(*)
28
- # /projects/test.rb:2
29
- # > IO#write(*)
30
- # /projects/test.rb:2
23
+ # > IO#<<(?)
24
+ # /projects/test.rb:1
25
+ # > IO#write(*)
26
+ # /projects/test.rb:1
27
+ # > IO#puts(*)
28
+ # /projects/test.rb:2
29
+ # > IO#write(*)
30
+ # /projects/test.rb:2
31
31
  ```
32
32
 
33
33
  When you need to know if exceptions are raised and handled you can use `ImLost.trace_exceptions`:
@@ -39,12 +39,12 @@ rescue SystemCallError
39
39
  raise('something went wrong!')
40
40
  end
41
41
  # output will look like
42
- # x Errno::EEXIST: File exists @ rb_sysopen - /
43
- # /projects/test.rb:2
44
- # ! Errno::EEXIST: File exists @ rb_sysopen - /
45
- # /projects/test.rb:3
46
- # x RuntimeError: something went wrong!
47
- # /projects/test.rb:4
42
+ # x Errno::EEXIST: File exists @ rb_sysopen - /
43
+ # /projects/test.rb:2
44
+ # ! Errno::EEXIST: File exists @ rb_sysopen - /
45
+ # /projects/test.rb:3
46
+ # x RuntimeError: something went wrong!
47
+ # /projects/test.rb:4
48
48
  ```
49
49
 
50
50
  When you like to know if and when a code point is reached, `ImLost.here` will help:
@@ -53,11 +53,28 @@ When you like to know if and when a code point is reached, `ImLost.here` will he
53
53
  ImLost.here
54
54
  ```
55
55
 
56
+ If you like to know the instance variables values of an object, use
57
+ `ImLost.vars`:
58
+
59
+ ```ruby
60
+ ImLost.vars(self)
61
+ ```
62
+
63
+ Or you can print the current local variables:
64
+
65
+ ```ruby
66
+ ImLost.vars(binding)
67
+ ```
68
+
69
+ See the [online help](https://rubydoc.info/gems/im-lost/ImLost) for more!
70
+
56
71
  ## Example
57
72
 
58
73
  ```ruby
59
74
  require 'im-lost'
60
75
 
76
+ require_relative '../lib/im-lost'
77
+
61
78
  class Foo
62
79
  def self.create(value:) = new(value)
63
80
 
@@ -82,8 +99,13 @@ my_foo = Foo.create(value: :foo!)
82
99
  ImLost.trace(my_foo)
83
100
 
84
101
  my_foo.foo(1, key: :none)
102
+ ImLost.vars(my_foo)
103
+
85
104
  my_foo.foo(2, :a, :b, :c, key: :some, name: :value)
105
+ ImLost.vars(my_foo)
106
+
86
107
  my_foo.foo(3) { puts _1 }
108
+ ImLost.vars(my_foo)
87
109
 
88
110
  # output will look like
89
111
  # > Foo.create(:foo!)
@@ -91,9 +113,9 @@ my_foo.foo(3) { puts _1 }
91
113
  # > Foo.new(*)
92
114
  # /projects/foo.rb:6
93
115
  # < Foo.new(*)
94
- # = #<Foo:0x0000000100902418 @value=:foo!>
116
+ # = #<Foo:0x00000001030810c0 @value=:foo!>
95
117
  # < Foo.create(:foo!)
96
- # = #<Foo:0x0000000100902418 @value=:foo!>
118
+ # = #<Foo:0x00000001030810c0 @value=:foo!>
97
119
  # > Foo#foo(1, *[], :none, **{}, &nil)
98
120
  # /projects/foo.rb:28
99
121
  # > Foo#bar()
@@ -102,23 +124,32 @@ my_foo.foo(3) { puts _1 }
102
124
  # = :bar
103
125
  # < Foo#foo(1, *[], :none, **{}, &nil)
104
126
  # = "1-none-[]-{}-bar"
127
+ # = /projects/foo.rb:29
128
+ # instance variables:
129
+ # @value: "1-none-[]-{}-bar"
105
130
  # > Foo#foo(2, *[:a, :b, :c], :some, **{:name=>:value}, &nil)
106
- # /projects/foo.rb:29
131
+ # /projects/foo.rb:31
107
132
  # > Foo#bar()
108
133
  # /projects/foo.rb:15
109
134
  # < Foo#bar()
110
135
  # = :bar
111
136
  # < Foo#foo(2, *[:a, :b, :c], :some, **{:name=>:value}, &nil)
112
137
  # = "2-some-[a,b,c]-{:name=>:value}-bar"
113
- # > Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000100900578 /projects/foo.rb:30>)
114
- # /projects/foo.rb:30
138
+ # = /projects/foo.rb:32
139
+ # instance variables:
140
+ # @value: "2-some-[a,b,c]-{:name=>:value}-bar"
141
+ # > Foo#foo(3, *[], nil, **{}, &#<Proc:0x00000001030aee30 /projects/foo.rb:34>)
142
+ # /projects/foo.rb:34
115
143
  # > Foo#bar()
116
144
  # /projects/foo.rb:15
117
145
  # < Foo#bar()
118
146
  # = :bar
119
147
  # 3--[]-{}-bar
120
- # < Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000100900578 /projects/foo.rb:30>)
148
+ # < Foo#foo(3, *[], nil, **{}, &#<Proc:0x00000001030aee30 /projects/foo.rb:34>)
121
149
  # = nil
150
+ # = /projects/foo.rb:35
151
+ # instance variables:
152
+ # @value: "3--[]-{}-bar"
122
153
  ```
123
154
 
124
155
  See [examples dir](./examples) for more…
data/examples/foo.rb CHANGED
@@ -26,8 +26,13 @@ my_foo = Foo.create(value: :foo!)
26
26
  ImLost.trace(my_foo)
27
27
 
28
28
  my_foo.foo(1, key: :none)
29
+ ImLost.vars(my_foo)
30
+
29
31
  my_foo.foo(2, :a, :b, :c, key: :some, name: :value)
32
+ ImLost.vars(my_foo)
33
+
30
34
  my_foo.foo(3) { puts _1 }
35
+ ImLost.vars(my_foo)
31
36
 
32
37
  # output will look like
33
38
  # > Foo.create(:foo!)
@@ -35,9 +40,9 @@ my_foo.foo(3) { puts _1 }
35
40
  # > Foo.new(*)
36
41
  # /projects/foo.rb:6
37
42
  # < Foo.new(*)
38
- # = #<Foo:0x0000000100902418 @value=:foo!>
43
+ # = #<Foo:0x00000001030810c0 @value=:foo!>
39
44
  # < Foo.create(:foo!)
40
- # = #<Foo:0x0000000100902418 @value=:foo!>
45
+ # = #<Foo:0x00000001030810c0 @value=:foo!>
41
46
  # > Foo#foo(1, *[], :none, **{}, &nil)
42
47
  # /projects/foo.rb:28
43
48
  # > Foo#bar()
@@ -46,20 +51,29 @@ my_foo.foo(3) { puts _1 }
46
51
  # = :bar
47
52
  # < Foo#foo(1, *[], :none, **{}, &nil)
48
53
  # = "1-none-[]-{}-bar"
54
+ # = /projects/foo.rb:29
55
+ # instance variables:
56
+ # @value: "1-none-[]-{}-bar"
49
57
  # > Foo#foo(2, *[:a, :b, :c], :some, **{:name=>:value}, &nil)
50
- # /projects/foo.rb:29
58
+ # /projects/foo.rb:31
51
59
  # > Foo#bar()
52
60
  # /projects/foo.rb:15
53
61
  # < Foo#bar()
54
62
  # = :bar
55
63
  # < Foo#foo(2, *[:a, :b, :c], :some, **{:name=>:value}, &nil)
56
64
  # = "2-some-[a,b,c]-{:name=>:value}-bar"
57
- # > Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000100900578 /projects/foo.rb:30>)
58
- # /projects/foo.rb:30
65
+ # = /projects/foo.rb:32
66
+ # instance variables:
67
+ # @value: "2-some-[a,b,c]-{:name=>:value}-bar"
68
+ # > Foo#foo(3, *[], nil, **{}, &#<Proc:0x00000001030aee30 /projects/foo.rb:34>)
69
+ # /projects/foo.rb:34
59
70
  # > Foo#bar()
60
71
  # /projects/foo.rb:15
61
72
  # < Foo#bar()
62
73
  # = :bar
63
74
  # 3--[]-{}-bar
64
- # < Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000100900578 /projects/foo.rb:30>)
75
+ # < Foo#foo(3, *[], nil, **{}, &#<Proc:0x00000001030aee30 /projects/foo.rb:34>)
65
76
  # = nil
77
+ # = /projects/foo.rb:35
78
+ # instance variables:
79
+ # @value: "3--[]-{}-bar"
@@ -2,5 +2,5 @@
2
2
 
3
3
  module ImLost
4
4
  # The version number of the gem.
5
- VERSION = '1.0.0'
5
+ VERSION = '1.0.2'
6
6
  end
data/lib/im-lost.rb CHANGED
@@ -1,5 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # If you have overlooked something again and don't really understand what your
4
+ # code is doing. If you have to maintain this application but can't really find
5
+ # your way around and certainly can't track down that stupid error. If you feel
6
+ # lost in all that code, here's the gem to help you out!
7
+ #
8
+ # ImLost helps you by analyzing function calls of objects, informing you about
9
+ # exceptions and logging your way through your code. In short, ImLost is your
10
+ # debugging helper!
11
+ #
3
12
  module ImLost
4
13
  class << self
5
14
  #
@@ -226,6 +235,28 @@ module ImLost
226
235
  self
227
236
  end
228
237
 
238
+ #
239
+ # Inspect internal variables.
240
+ #
241
+ # @overload vars(binding)
242
+ # Inspect local variables of given Binding.
243
+ # @param binding [Binding] which local variables should be print
244
+ # @return [self] itself
245
+ #
246
+ # @overload vars(object)
247
+ # Inspect instance variables of given object.
248
+ # @param object [Object] which instance variables should be print
249
+ # @return [Object] the given object
250
+ #
251
+ def vars(object)
252
+ traced = @trace.delete(object.__id__)
253
+ return _local_vars(object) if object.is_a?(Binding)
254
+ return unless object.respond_to?(:instance_variables)
255
+ _vars(object, Kernel.caller_locations(1, 1)[0])
256
+ ensure
257
+ @trace[traced] = traced if traced
258
+ end
259
+
229
260
  protected
230
261
 
231
262
  def as_sig(prefix, info, args)
@@ -241,41 +272,73 @@ module ImLost
241
272
  private
242
273
 
243
274
  def _trace(arg)
244
- @trace[arg.__id__] = 1 if self != arg && @output != arg
275
+ id = arg.__id__
276
+ @trace[id] = id if __id__ != id && @output.__id__ != id
245
277
  arg
246
278
  end
247
279
 
248
280
  def _trace_all(args)
249
281
  args.each do |arg|
250
- @trace[arg.__id__] = 1 if arg != self && @output != arg
282
+ arg = arg.__id__
283
+ @trace[arg] = arg if __id__ != arg && @output.__id__ != arg
251
284
  end
252
285
  args
253
286
  end
254
287
 
255
288
  def _trace_b(arg)
256
- @trace[id = arg.__id__] = 1 if self != arg && @output != arg
257
- yield(arg)
258
- ensure
259
- @trace.delete(id) if id
289
+ id = arg.__id__
290
+ return yield(arg) if __id__ == id || @output.__id__ == id
291
+ begin
292
+ @trace[id] = id
293
+ yield(arg)
294
+ ensure
295
+ @trace.delete(id) if id
296
+ end
260
297
  end
261
298
 
262
299
  def _trace_all_b(args)
263
300
  ids =
264
301
  args.filter_map do |arg|
265
- next if self == arg || @output == arg
266
- @trace[id = arg.__id__] = 1
267
- id
302
+ arg = arg.__id__
303
+ @trace[arg] = arg if __id__ != arg && @output.__id__ != arg
268
304
  end
269
305
  yield(args)
270
306
  ensure
271
307
  ids.each { @trace.delete(_1) }
272
308
  end
309
+
310
+ def _vars(obj, location)
311
+ @output.puts("= #{location.path}:#{location.lineno}")
312
+ vars = obj.instance_variables
313
+ if vars.empty?
314
+ @output.puts(' <no instance variables defined>')
315
+ else
316
+ @output.puts(' instance variables:')
317
+ vars.sort!.each do |name|
318
+ @output.puts(" #{name}: #{obj.instance_variable_get(name).inspect}")
319
+ end
320
+ end
321
+ obj
322
+ end
323
+
324
+ def _local_vars(binding)
325
+ @output.puts("= #{binding.source_location.join(':')}")
326
+ vars = binding.local_variables
327
+ if vars.empty?
328
+ @output.puts(' <no local variables>')
329
+ else
330
+ @output.puts(' local variables:')
331
+ vars.sort!.each do |name|
332
+ @output.puts(" #{name}: #{binding.local_variable_get(name).inspect}")
333
+ end
334
+ end
335
+ self
336
+ end
273
337
  end
274
338
 
275
339
  ARG_SIG = { rest: '*', keyrest: '**', block: '&' }.compare_by_identity.freeze
276
- NO_NAME = %i[* ** &].freeze
277
- EX_PREFIX = { raise: 'x', rescue: '!' }.freeze
278
- private_constant :ARG_SIG, :NO_NAME, :EX_PREFIX
340
+ NO_NAME = { :* => 1, :** => 1, :& => 1 }.compare_by_identity.freeze
341
+ private_constant :ARG_SIG, :NO_NAME
279
342
 
280
343
  @trace = {}.compare_by_identity
281
344
  @caller_locations = true
@@ -283,19 +346,19 @@ module ImLost
283
346
 
284
347
  @trace_calls = [
285
348
  TracePoint.new(:c_call) do |tp|
286
- next unless @trace.key?(tp.self.__id__)
349
+ next if !@trace.key?(tp.self.__id__) || tp.path == __FILE__
287
350
  @output.puts(as_sig('>', tp, tp.parameters.map { ARG_SIG[_1[0]] || '?' }))
288
351
  @output.puts(" #{tp.path}:#{tp.lineno}") if @caller_locations
289
352
  end,
290
353
  TracePoint.new(:call) do |tp|
291
- next unless @trace.key?(tp.self.__id__)
354
+ next if !@trace.key?(tp.self.__id__) || tp.path == __FILE__
292
355
  ctx = tp.binding
293
356
  @output.puts(
294
357
  as_sig(
295
358
  '>',
296
359
  tp,
297
360
  tp.parameters.map do |kind, name|
298
- next name if NO_NAME.include?(name)
361
+ next name if NO_NAME.key?(name)
299
362
  "#{ARG_SIG[kind]}#{ctx.local_variable_get(name).inspect}"
300
363
  end
301
364
  )
@@ -308,12 +371,12 @@ module ImLost
308
371
 
309
372
  @trace_results = [
310
373
  TracePoint.new(:c_return) do |tp|
311
- next unless @trace.key?(tp.self.__id__)
374
+ next if !@trace.key?(tp.self.__id__) || tp.path == __FILE__
312
375
  @output.puts(as_sig('<', tp, tp.parameters.map { ARG_SIG[_1[0]] || '?' }))
313
376
  @output.puts(" = #{tp.return_value.inspect}")
314
377
  end,
315
378
  TracePoint.new(:return) do |tp|
316
- next unless @trace.key?(tp.self.__id__)
379
+ next if !@trace.key?(tp.self.__id__) || tp.path == __FILE__
317
380
  ctx = tp.binding
318
381
  @output.puts(
319
382
  as_sig(
@@ -333,7 +396,9 @@ module ImLost
333
396
  @trace_exceptions =
334
397
  TracePoint.new(*supported) do |tp|
335
398
  ex = tp.raised_exception.inspect
336
- @output.puts("#{EX_PREFIX[tp.event]} #{ex[0] == '#' ? ex[2..-2] : ex}")
399
+ @output.puts(
400
+ "#{tp.event == :raise ? 'x' : '!'} #{ex[0] == '#' ? ex[2..-2] : ex}"
401
+ )
337
402
  @output.puts(" #{tp.path}:#{tp.lineno}") if @exception_locations
338
403
  end
339
404
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: im-lost
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-12 00:00:00.000000000 Z
11
+ date: 2024-05-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  If you have overlooked something again and don't really understand what