summaryrefslogtreecommitdiff
path: root/lib/pry/commands/wtf.rb
blob: 3e25dca3f86a0ded935f2e90012a505141baddbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# frozen_string_literal: true

class Pry
  class Command
    class Wtf < Pry::ClassCommand
      match(/wtf([?!]*)/)
      group 'Context'
      description 'Show the backtrace of the most recent exception.'
      options listing: 'wtf?'

      banner <<-'BANNER'
        Usage: wtf[?|!]

        Show's a few lines of the backtrace of the most recent exception (also available
        as `_ex_.backtrace`). If you want to see more lines, add more question marks or
        exclamation marks.

        wtf?
        wtf?!???!?!?

        # To see the entire backtrace, pass the `-v` or `--verbose` flag.
        wtf -v
      BANNER

      def options(opt)
        opt.on :v, :verbose, "Show the full backtrace"
      end

      def process
        raise Pry::CommandError, "No most-recent exception" unless exception

        output.puts "#{bold('Exception:')} #{exception.class}: #{exception}\n--"
        if opts.verbose?
          output.puts with_line_numbers(backtrace)
        else
          output.puts with_line_numbers(backtrace.first(size_of_backtrace))
        end

        return unless exception.respond_to?(:cause)

        cause = exception.cause
        while cause
          output.puts "#{bold('Caused by:')} #{cause.class}: #{cause}\n--"
          if opts.verbose?
            output.puts with_line_numbers(cause.backtrace)
          else
            output.puts with_line_numbers(cause.backtrace.first(size_of_backtrace))
          end
          cause = cause.cause
        end
      end

      private

      def exception
        pry_instance.last_exception
      end

      def with_line_numbers(backtrace)
        Pry::Code.new(backtrace, 0, :text).with_line_numbers.to_s
      end

      def backtrace
        exception.backtrace
      end

      def size_of_backtrace
        [captures[0].size, 0.5].max * 10
      end
    end

    Pry::Commands.add_command(Pry::Command::Wtf)
  end
end