File: breakpoint.rb

package info (click to toggle)
ruby-pry-byebug 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 324 kB
  • sloc: ruby: 1,171; makefile: 4
file content (137 lines) | stat: -rw-r--r-- 4,298 bytes parent folder | download
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# frozen_string_literal: true

require "pry/byebug/breakpoints"
require "pry-byebug/helpers/breakpoints"
require "pry-byebug/helpers/location"
require "pry-byebug/helpers/multiline"

module PryByebug
  #
  # Add, show and remove breakpoints
  #
  class BreakCommand < Pry::ClassCommand
    include Helpers::Breakpoints
    include Helpers::Location
    include Helpers::Multiline

    match "break"
    group "Byebug"
    description "Set or edit a breakpoint."

    banner <<-BANNER
      Usage:   break <METHOD | FILE:LINE | LINE> [if CONDITION]
               break --condition N [CONDITION]
               break [--show | --delete | --enable | --disable] N
               break [--delete-all | --disable-all]
               break

      Set a breakpoint. Accepts a line number in the current file, a file and
      line number, or a method, and an optional condition.

      Pass appropriate flags to manipulate existing breakpoints.

      Examples:

        break SomeClass#run         Break at the start of `SomeClass#run`.
        break Foo#bar if baz?       Break at `Foo#bar` only if `baz?`.
        break app/models/user.rb:15 Break at line 15 in user.rb.
        break 14                    Break at line 14 in the current file.

        break --condition 4 x > 2   Add/change condition on breakpoint #4.
        break --condition 3         Remove the condition on breakpoint #3.

        break --delete 5            Delete breakpoint #5.
        break --disable-all         Disable all breakpoints.

        break --show 2              Show details about breakpoint #2.
        break                       List all breakpoints.
    BANNER

    def options(opt)
      defaults = { argument: true, as: Integer }

      opt.on :c, :condition, "Change condition of a breakpoint.", defaults
      opt.on :s, :show, "Show breakpoint details and source.", defaults
      opt.on :D, :delete, "Delete a breakpoint.", defaults
      opt.on :d, :disable, "Disable a breakpoint.", defaults
      opt.on :e, :enable, "Enable a disabled breakpoint.", defaults
      opt.on :'disable-all', "Disable all breakpoints."
      opt.on :'delete-all', "Delete all breakpoints."
    end

    def process
      return if check_multiline_context

      PryByebug.check_file_context(target)

      option, = opts.to_hash.find { |key, _value| opts.present?(key) }
      return send(option_to_method(option)) if option

      return new_breakpoint unless args.empty?

      print_all
    end

    private

    %w[delete disable enable disable_all delete_all].each do |command|
      define_method(:"process_#{command}") do
        breakpoints.send(*[command, opts[command]].compact)
        print_all
      end
    end

    def process_show
      print_full_breakpoint(breakpoints.find_by_id(opts[:show]))
    end

    def process_condition
      expr = args.empty? ? nil : args.join(" ")
      breakpoints.change(opts[:condition], expr)
    end

    def new_breakpoint
      place = args.shift
      condition = args.join(" ") if args.shift == "if"

      bp = add_breakpoint(place, condition)

      print_full_breakpoint(bp)
    end

    def option_to_method(option)
      "process_#{option.to_s.tr('-', '_')}"
    end

    def print_all
      print_breakpoints_header
      breakpoints.each { |b| print_short_breakpoint(b) }
    end

    def add_breakpoint(place, condition)
      case place
      when /^(\d+)$/
        errmsg = "Line number declaration valid only in a file context."
        PryByebug.check_file_context(target, errmsg)

        lineno = Regexp.last_match[1].to_i
        breakpoints.add_file(current_file, lineno, condition)
      when /^(.+):(\d+)$/
        file = Regexp.last_match[1]
        lineno = Regexp.last_match[2].to_i
        breakpoints.add_file(file, lineno, condition)
      when /^(.*)[.#].+$/ # Method or class name
        if Regexp.last_match[1].strip.empty?
          errmsg = "Method name declaration valid only in a file context."
          PryByebug.check_file_context(target, errmsg)
          place = target.eval("self.class.to_s") + place
        end
        breakpoints.add_method(place, condition)
      else
        raise(ArgumentError, "Cannot identify arguments as breakpoint")
      end
    end
  end
end

Pry::Commands.add_command(PryByebug::BreakCommand)