byebug 1.2.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/GUIDE.md +210 -4
  4. data/README.md +93 -64
  5. data/bin/byebug +10 -4
  6. data/byebug.gemspec +1 -1
  7. data/ext/byebug/breakpoint.c +22 -20
  8. data/lib/byebug/command.rb +5 -3
  9. data/lib/byebug/commands/frame.rb +2 -1
  10. data/lib/byebug/commands/kill.rb +0 -1
  11. data/lib/byebug/commands/set.rb +5 -6
  12. data/lib/byebug/commands/show.rb +11 -11
  13. data/lib/byebug/version.rb +1 -1
  14. data/logo.png +0 -0
  15. data/old_doc/byebug.texi +2 -2
  16. data/old_doc/{test-tri2.rb → test-triangle.rb} +4 -5
  17. data/old_doc/tri3.rb +3 -5
  18. data/old_doc/triangle.rb +4 -2
  19. data/test/breakpoints_test.rb +1 -2
  20. data/test/conditions_test.rb +3 -4
  21. data/test/continue_test.rb +6 -8
  22. data/test/display_test.rb +1 -2
  23. data/test/edit_test.rb +1 -2
  24. data/test/eval_test.rb +1 -2
  25. data/test/examples/stepping.rb +4 -0
  26. data/test/finish_test.rb +1 -2
  27. data/test/frame_test.rb +1 -2
  28. data/test/help_test.rb +1 -2
  29. data/test/info_test.rb +1 -2
  30. data/test/jump_test.rb +1 -2
  31. data/test/kill_test.rb +1 -2
  32. data/test/list_test.rb +1 -2
  33. data/test/method_test.rb +1 -2
  34. data/test/post_mortem_test.rb +1 -2
  35. data/test/quit_test.rb +1 -2
  36. data/test/reload_test.rb +1 -2
  37. data/test/repl_test.rb +1 -2
  38. data/test/restart_test.rb +1 -2
  39. data/test/save_test.rb +1 -2
  40. data/test/set_test.rb +6 -11
  41. data/test/show_test.rb +5 -4
  42. data/test/source_test.rb +1 -2
  43. data/test/stepping_test.rb +81 -55
  44. data/test/support/test_dsl.rb +54 -54
  45. data/test/test_helper.rb +0 -1
  46. data/test/trace_test.rb +75 -80
  47. data/test/variables_test.rb +1 -2
  48. metadata +6 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 889f4fe2a663bd2b3f7bf9d03f6b82971cfcb3ad
4
- data.tar.gz: 1d8c1667bb48110e5cca851b5f50a799fa0b54dc
3
+ metadata.gz: f2ab6f03625dc6bba2088e27bff9ec5f6c335b57
4
+ data.tar.gz: 48cca8a66cb638c91a26728a334613c33359236b
5
5
  SHA512:
6
- metadata.gz: 6f268a0212666405a1f80188575158ad64d19853e11950bc50decf2a36b81eecca3565513e068bb004a391038354a0f016226e561e12a4988e213993a773345e
7
- data.tar.gz: 1cf89b9b021e749a06cbe2141146b632846d7cd7d1f21f584870967fb85f8e278195050829e16380cbc6bc1d4ab92bc79c62966872275819752b113ccd89ef30
6
+ metadata.gz: 0a7c63ad6c37d3d23f13aa5db25db6dec3bed363ece29fc40402d3fa852ab2255183bb3d705c394d4a6c8a62a81f88e45e8bab5786dc06aff92eea02b9309112
7
+ data.tar.gz: 5274f6aa1ab234bd028ae07943cdbfa0bfa9f02a82e5925566a55e6f6a383fbabfeb6cbc9da64efb56b3098fbeb4320ba207485ccf4ed2aa812efe98c35bc1c7
@@ -1,3 +1,8 @@
1
+ ## 1.3.0
2
+
3
+ * Support colon-delimited include paths in command-line front-end (@ender672)
4
+
5
+
1
6
  ## 1.2.0
2
7
 
3
8
  * Added 'pry' command.
data/GUIDE.md CHANGED
@@ -190,7 +190,7 @@ resumes execution. Notice the difference between `display a` and
190
190
  after it is evaluated. To remove a display expression `undisplay` is used. If we
191
191
  give a display number, just that display expression is removed.
192
192
 
193
- We also used a new command `where`(see [Backtrace]()) to show the call stack. In
193
+ We also used a new command `where`(see [backtrace]()) to show the call stack. In
194
194
  the above situation, starting from the bottom line we see we called the `hanoi`
195
195
  method from line 34 of the file `hanoi.rb` and the `hanoi` method called itself
196
196
  two more times at line 4.
@@ -200,9 +200,9 @@ being called, the names of the parameters, the types those parameters
200
200
  _currently_ have and the file-line position. Remember it's possible that when
201
201
  the program was called the parameters had different types, since the types of
202
202
  variables can change dynamically. You can alter the style of what to show in the
203
- trace (see [Callstyle]()).
203
+ trace (see [callstyle]()).
204
204
 
205
- Now let's more around the callstack.
205
+ Now let's move around the callstack.
206
206
 
207
207
  ```
208
208
  (byebug) undisplay
@@ -223,9 +223,215 @@ NameError Exception: undefined local variable or method `i_args' for main:Object
223
223
 
224
224
  Notice in the above to get the value of variable `n` we had to use a print
225
225
  command like `p n`. If we entered just `n`, that would be taken to mean byebug
226
- command ``next''. In the current scope, variable `i_args` is not defined.
226
+ command `next`. In the current scope, variable `i_args` is not defined.
227
227
  However I can change to the top-most frame by using the `frame` command. Just as
228
228
  with arrays, -1 means the last one. Alternatively using frame number 3 would
229
229
  have been the same thing; so would issuing `up 3`. Note that in the outside
230
230
  frame #3, the value of `i_args` can be shown. Also note that the value of
231
231
  variable `n` is different.
232
+
233
+
234
+ ## Unit Testing Session
235
+
236
+ In the previous sessions we've been calling byebug right at the outset, but this
237
+ is probably not the mode of operation you will use the most. There are a number
238
+ of situations where calling byebug at the outset is impractical for a couple of
239
+ reasons:
240
+
241
+ * Byebug just doesn't work when run at the outset. Any debugging changes the
242
+ behavior or the program in slight and subtle ways, and sometimes this can hinder
243
+ finding bugs.
244
+ * There's a lot of code that needs to be run before the part you want to
245
+ inspect. Running this code takes time and you don't want the overhead of
246
+ byebug.
247
+
248
+ In this section we'll show how to enter the code in the middle of your program,
249
+ while delving more into byebug's operation. We will also use unit testing. Using
250
+ unit tests will greatly reduce the amount of debugging needed, while at the same
251
+ time, will increase the quality of your program.
252
+
253
+ What we'll do is take the `triangle` code from the first session and write a
254
+ unit test for that. In a sense we did write a tiny test for the program which
255
+ was basically the last line where we printed the value of `triangle(3)`. This
256
+ test however wasn't automated: the expectation is that someone would look at the
257
+ output and verify that what was printed is what was expected.
258
+
259
+ Before we can turn that into something that can be `required`, we probably want
260
+ to remove that output. However I like to keep in that line so that when I
261
+ look at the file, I have an example of how to run it. Therefore we will
262
+ conditionally run this line if that file is invoked directly, but skip it if it
263
+ is not. _NOTE: `byebug` resets `$0` to try to make things like this work._
264
+
265
+ ```
266
+ if __FILE__ == $0
267
+ t = triangle(3)
268
+ puts t
269
+ end
270
+ ```
271
+
272
+ Okay, we're now ready to write our unit test. We'll use `test/unit` which comes
273
+ with the standard Ruby distribution. Here's the test code; it should be in the
274
+ same directory as `triangle.rb`.
275
+
276
+ ```ruby
277
+ require 'test/unit'
278
+ require_relative 'triangle.rb'
279
+
280
+ class TestTri < Test::Unit::TestCase
281
+ def test_basic
282
+ solutions = []
283
+ 0.upto(5) do |i|
284
+ solutions << triangle(i)
285
+ end
286
+ assert_equal([0, 1, 3, 6, 10, 15], solutions,
287
+ 'Testing the first 5 triangle numbers')
288
+ end
289
+ end
290
+ ```
291
+
292
+ Let's say we want to stop before the first statement in our test method, we'll
293
+ add the following:
294
+
295
+ ```ruby
296
+ ...
297
+ def test_basic
298
+ require 'byebug'
299
+ byebug
300
+ solutions = []
301
+ ...
302
+ ```
303
+
304
+ Now we run the program..
305
+ ```
306
+ $ ruby test-triangle.rb
307
+ Run options:
308
+
309
+ # Running tests:
310
+
311
+ [1/1] TestTri#test_basic[5, 14] in test-triangle.rb
312
+ 5:
313
+ 6: class TestTri < Test::Unit::TestCase
314
+ 7: def test_basic
315
+ 8: require 'byebug'
316
+ 9: byebug
317
+ => 10: solutions = []
318
+ 11: 0.upto(5) do |i|
319
+ 12: solutions << triangle(i)
320
+ 13: end
321
+ 14: assert_equal([0, 1, 3, 6, 10, 15], solutions,
322
+ (byebug)
323
+ ```
324
+
325
+ and we see that we are stopped at line 10 just before the initialization of the
326
+ list `solutions`.
327
+
328
+ Now let's see where we are...
329
+ ```
330
+ (byebug) where
331
+ --> #0 TestTri.test_basic at test-tri2.rb:10
332
+ Warning: saved frames may be incomplete; compare with caller(0)
333
+ (byebug)
334
+ ```
335
+
336
+ Something seems wrong here; `TestTri.test_basic` indicates that we are in class
337
+ `TestTri` in method `test_basic`. However we don't see the call to this like we
338
+ did in the last example when we used the `where` command. This is because byebug
339
+ really didn't spring into existence until after we already had entered that
340
+ method, and Ruby doesn't keep call stack information around in a way that would
341
+ give the information we show when running `where`.
342
+
343
+ If we want call stack information, we have to turn call-stack tracking on
344
+ _beforehand_. This is done by adding `Byebug.start`.
345
+
346
+ Here's what our test program looks like after we modify it to start tracking
347
+ calls from the outset
348
+
349
+ ```ruby
350
+ require 'test/unit'
351
+ require_relative 'triangle.rb'
352
+ require 'byebug'
353
+ Byebug.start
354
+
355
+ class TestTri < Test::Unit::TestCase
356
+ def test_basic
357
+ byebug
358
+ solutions = []
359
+ 0.upto(5) do |i|
360
+ solutions << triangle(i)
361
+ end
362
+ assert_equal([0, 1, 3, 6, 10, 15], solutions,
363
+ "Testing the first 5 triangle numbers")
364
+ end
365
+ end
366
+ ```
367
+
368
+ Now when we run this:
369
+ ```
370
+ $ ruby test-triangle.rb
371
+ Run options:
372
+
373
+ # Running tests:
374
+
375
+ [1/1] TestTri#test_basic[5, 14] in test-triangle.rb
376
+ 5:
377
+ 6: class TestTri < Test::Unit::TestCase
378
+ 7: def test_basic
379
+ 8: require 'byebug'
380
+ 9: byebug
381
+ => 10: solutions = []
382
+ 11: 0.upto(5) do |i|
383
+ 12: solutions << triangle(i)
384
+ 13: end
385
+ 14: assert_equal([0, 1, 3, 6, 10, 15], solutions,
386
+ (byebug) where
387
+ --> #0 TestTri.test_basic at test-triangle.rb:10
388
+ #1 MiniTest::Unit::TestCase.run_test(name#String)
389
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:858
390
+ #2 MiniTest::Unit::TestCase.run(runner#Test::Unit::Runner)
391
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1301
392
+ #3 Test::Unit::TestCase.run(runner#Test::Unit::Runner)
393
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit/testcase.rb:17
394
+ #4 MiniTest::Unit._run_suite(suite#Class, type#Symbol)
395
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:919
396
+ #5 Array.map(suite#Class, type#Symbol)
397
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:912
398
+ #6 MiniTest::Unit._run_suite(suite#Class, type#Symbol)
399
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:912
400
+ #7 Test::Unit::Runner._run_suites(suites#Array, type#Symbol)
401
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:657
402
+ #8 Array.each(suites#Array, type#Symbol)
403
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:655
404
+ #9 Test::Unit::Runner._run_suites(suites#Array, type#Symbol)
405
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:655
406
+ #10 MiniTest::Unit._run_anything(type#Symbol)
407
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:867
408
+ #11 MiniTest::Unit.run_tests
409
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1060
410
+ #12 MiniTest::Unit._run(args#Array)
411
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1047
412
+ #13 Array.each(args#Array)
413
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1046
414
+ #14 MiniTest::Unit._run(args#Array)
415
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1046
416
+ #15 MiniTest::Unit._run(args#Array)
417
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1042
418
+ #16 MiniTest::Unit.run(args#Array)
419
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/minitest/unit.rb:1035
420
+ #17 Test::Unit::RunCount.run(args#NilClass)
421
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:21
422
+ #18 Test::Unit::Runner.run(args#Array)
423
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:774
424
+ #19 #<Class:Test::Unit::Runner>.autorun
425
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:366
426
+ #20 Test::Unit::RunCount.run_once
427
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:27
428
+ #21 #<Class:Test::Unit::Runner>.autorun
429
+ at /home/davidr/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/2.0.0/test/unit.rb:367
430
+ #22 <main> at test-triangle.rb:6
431
+ (byebug)
432
+ ```
433
+
434
+ Much better. But again let me emphasize that the parameter types are those of
435
+ the corresponding variables that _currently_ exist, and this might have changed
436
+ since the time when the call was made.
437
+
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Byebug [![Gem Version](https://badge.fury.io/rb/byebug.png)](http://badge.fury.io/rb/byebug) [![Build Status](https://secure.travis-ci.org/deivid-rodriguez/byebug.png)](http://travis-ci.org/deivid-rodriguez/byebug) [![Code Climate](https://codeclimate.com/github/deivid-rodriguez/byebug.png)](https://codeclimate.com/github/deivid-rodriguez/byebug) [![Dependency Status](https://gemnasium.com/deivid-rodriguez/byebug.png)](https://gemnasium.com/deivid-rodriguez/byebug)
2
2
 
3
+ <img src="https://raw.github.com/deivid-rodriguez/byebug/master/logo.png"
4
+ alt="Byebug logo" align="right" />
5
+
3
6
  _Debugging in Ruby 2.0_
4
7
 
5
8
  Byebug is a simple to use, feature rich debugger for Ruby 2.0. It uses the new
@@ -32,10 +35,51 @@ in your Gemfile and run
32
35
 
33
36
  ## Usage
34
37
 
35
- Simply drop `byebug` wherever you want to start debugging and the execution
36
- stop there. If you are debugging rails, start the server in normal mode with
37
- `rails server` and once the execution get to your `byebug` command you will get
38
- a debugging terminal.
38
+ Simply drop
39
+
40
+ byebug
41
+
42
+ wherever you want to start debugging and the execution will stop there. If you
43
+ are debugging rails, start the server in normal mode with `rails server` and
44
+ once the execution get to your `byebug` command you will get a debugging
45
+ terminal.
46
+
47
+ _If you are coming from debugger, notice that stopping execution using the word
48
+ `debugger` doesn't work anymore unless you explicitly alias it._
49
+
50
+ ### Configuration
51
+
52
+ You can automatically load some configurations at startup by dropping them in
53
+ the startup file `.byebugrc`. For example, you can change the number of lines
54
+ listed whenever byebug stops like this:
55
+
56
+ set listsize 20
57
+
58
+ If you are coming from [debugger](https://github.com/cldwalker/debugger), notice
59
+ however that you no longer need
60
+
61
+ set autoreload
62
+
63
+ because it is a default option in byebug.
64
+
65
+
66
+ ## What's different from debugger
67
+
68
+ * Works on 2.0.0 and it doesn't on 1.9.x.
69
+ * Has no MRI internal source code dependencies, just a clean API.
70
+ * Fixes most of debugger's current open issues:
71
+ - Post mortem mode segfaulting.
72
+ - Line number wrongly shown as zero in backtrace.
73
+ - Line tracing.
74
+ - Colon delimited include paths.
75
+ - Nice markdow guide.
76
+ - Ruby 2.0 support.
77
+ * Very actively mantained.
78
+ * Editor agnostic: no external editor built-in support.
79
+ * No thread support as not supported by the new API yet (I hope it will come
80
+ soon!).
81
+ * Pry command is built-in. No need of external gem like debugger-pry.
82
+
39
83
 
40
84
  ## Getting Started
41
85
 
@@ -46,15 +90,15 @@ number of a given length (there are shorter ways to do it, of course).
46
90
  ```
47
91
  $ byebug triangle.rb
48
92
  [1, 10] in /home/davidr/Proyectos/byebug/old_doc/triangle.rb
49
- 1: # Compute the n'th triangle number: triangle(n) == (n*(n+1))/2
50
- => 2: def triangle(n)
51
- 3: tri = 0
52
- 4: 0.upto(n) do |i|
53
- 5: tri += i
54
- 6: end
55
- 7: tri
56
- 8: end
57
- 9:
93
+ 1: # Compute the n'th triangle number: triangle(n) == (n*(n+1))/2
94
+ => 2: def triangle(n)
95
+ 3: tri = 0
96
+ 4: 0.upto(n) do |i|
97
+ 5: tri += i
98
+ 6: end
99
+ 7: tri
100
+ 8: end
101
+ 9:
58
102
  10: t = triangle(3)
59
103
  (byebug)
60
104
  ```
@@ -81,41 +125,41 @@ Now let us step through the program.
81
125
  ```
82
126
  (byebug) step
83
127
  [2, 11] in /home/davidr/Proyectos/byebug/old_doc/triangle.rb
84
- 2: def triangle(n)
85
- 3: tri = 0
86
- 4: 0.upto(n) do |i|
87
- 5: tri += i
88
- 6: end
89
- 7: tri
90
- 8: end
91
- 9:
128
+ 2: def triangle(n)
129
+ 3: tri = 0
130
+ 4: 0.upto(n) do |i|
131
+ 5: tri += i
132
+ 6: end
133
+ 7: tri
134
+ 8: end
135
+ 9:
92
136
  => 10: t = triangle(3)
93
137
  11: puts t
94
138
  (byebug) <RET> # hit enter
95
139
  [1, 10] in /home/davidr/Proyectos/byebug/old_doc/triangle.rb
96
- 1: # Compute the n'th triangle number: triangle(n) == (n*(n+1))/2
97
- 2: def triangle(n)
98
- => 3: tri = 0
99
- 4: 0.upto(n) do |i|
100
- 5: tri += i
101
- 6: end
102
- 7: tri
103
- 8: end
104
- 9:
140
+ 1: # Compute the n'th triangle number: triangle(n) == (n*(n+1))/2
141
+ 2: def triangle(n)
142
+ => 3: tri = 0
143
+ 4: 0.upto(n) do |i|
144
+ 5: tri += i
145
+ 6: end
146
+ 7: tri
147
+ 8: end
148
+ 9:
105
149
  10: t = triangle(3)
106
150
  (byebug) p tri
107
151
  nil
108
152
  (byebug) step
109
153
  [1, 10] in /home/davidr/Proyectos/byebug/old_doc/triangle.rb
110
- 1: # Compute the n'th triangle number: triangle(n) == (n*(n+1))/2
111
- 2: def triangle(n)
112
- 3: tri = 0
113
- => 4: 0.upto(n) do |i|
114
- 5: tri += i
115
- 6: end
116
- 7: tri
117
- 8: end
118
- 9:
154
+ 1: # Compute the n'th triangle number: triangle(n) == (n*(n+1))/2
155
+ 2: def triangle(n)
156
+ 3: tri = 0
157
+ => 4: 0.upto(n) do |i|
158
+ 5: tri += i
159
+ 6: end
160
+ 7: tri
161
+ 8: end
162
+ 9:
119
163
  10: t = triangle(3)
120
164
  (byebug) p tri
121
165
  0
@@ -168,14 +212,14 @@ Tracing: triangle.rb:11 puts t
168
212
  1: tri =
169
213
  2: i =
170
214
  [2, 11] in /home/davidr/Proyectos/byebug/old_doc/triangle.rb
171
- 2: def triangle(n)
172
- 3: tri = 0
173
- 4: 0.upto(n) do |i|
174
- 5: tri += i
175
- 6: end
176
- 7: tri
177
- 8: end
178
- 9:
215
+ 2: def triangle(n)
216
+ 3: tri = 0
217
+ 4: 0.upto(n) do |i|
218
+ 5: tri += i
219
+ 6: end
220
+ 7: tri
221
+ 8: end
222
+ 9:
179
223
  10: t = triangle(3)
180
224
  => 11: puts t
181
225
  1: tri =
@@ -189,23 +233,7 @@ can issue a `quit` command (`q` and `exit` are just as good). If you want to
189
233
  quit without being prompted, suffix the command with an exclamation mark, e.g.,
190
234
  `q!`.
191
235
 
192
- ### The rest of the tutorial is available
193
- [here](https://github.com/deivid-rodriguez/byebug/blob/master/GUIDE.md)
194
-
195
- ## Configuration
196
-
197
- You can automatically load some configurations at startup by dropping them in
198
- the startup file `.byebugrc`. For example, you can change the number of lines
199
- listed whenever byebug stops like this:
200
-
201
- set listsize 20
202
-
203
- If you are coming from [debugger](https://github.com/cldwalker/debugger), notice
204
- however that you no longer need
205
-
206
- set autoreload
207
-
208
- because it is a default option in byebug.
236
+ ### The rest of the tutorial is available [here](https://github.com/deivid-rodriguez/byebug/blob/master/GUIDE.md)
209
237
 
210
238
 
211
239
  ## Related projects
@@ -225,3 +253,4 @@ software, specially:
225
253
  * Koichi Sasada, author of the new C debugging API for Ruby.
226
254
  * Dennis Ushakov, author of [debase](https://github.com/denofevil/debase), the
227
255
  starting point of this.
256
+ * Logo by [Ivlichev Victor Petrovich](http://www.aha-soft.com/)