Class: Canopus::Debug::Panel

Inherits:
Object
  • Object
show all
Defined in:
lib/canopus/debug/panel.rb

Constant Summary collapse

ITEM_LIMIT =
1_000
WATCH_LIMIT =
100
TEXT_LIMIT =
4_096
DEPTH_LIMIT =
32
ROOT_STACK =
[:debug, :stack].freeze
ROOT_VARIABLES =
[:debug, :variables].freeze
ROOT_WATCHES =
[:debug, :watches].freeze
ROOT_BREAKPOINTS =
[:debug, :breakpoints].freeze
ROOTS =
[ROOT_STACK, ROOT_VARIABLES, ROOT_WATCHES, ROOT_BREAKPOINTS].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(breakpoints:, post:, select_frame:, select_breakpoint:, report:, request_frame:) ⇒ Panel

Returns a new instance of Panel.

Raises:

  • (ArgumentError)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/canopus/debug/panel.rb', line 21

def initialize(breakpoints:, post:, select_frame:, select_breakpoint:, report:, request_frame:)
  callbacks = [post, select_frame, select_breakpoint, report, request_frame]
  raise ArgumentError, "debug panel callbacks must be callable" unless callbacks.all? { |item| item.respond_to?(:call) }

  @breakpoints = breakpoints
  @post, @select_frame, @select_breakpoint = post, select_frame, select_breakpoint
  @report, @request_frame = report, request_frame
  @generation = 0
  @pending = Set.new
  @watches = [].freeze
  @watch_tokens = {}
  @expanded_paths = Set.new
  @expanded_roots = ROOTS.to_set
  @stack_frames, @watch_results = [], {}
  @tree = Zaniah::UI::TreeView.new(nodes, height: 600)
    .on_select { |value, _event, _context| select(value) }
    .on_toggle { |id, open| remember_expansion(id, open) }
  restore_expansions
end

Instance Attribute Details

#expanded_paths ⇒ Object (readonly)

Returns the value of attribute expanded_paths.



19
20
21
# File 'lib/canopus/debug/panel.rb', line 19

def expanded_paths
  @expanded_paths
end

#selected_frame ⇒ Object (readonly)

Returns the value of attribute selected_frame.



19
20
21
# File 'lib/canopus/debug/panel.rb', line 19

def selected_frame
  @selected_frame
end

#tree ⇒ Object (readonly)

Returns the value of attribute tree.



19
20
21
# File 'lib/canopus/debug/panel.rb', line 19

def tree
  @tree
end

#watches ⇒ Object (readonly)

Returns the value of attribute watches.



19
20
21
# File 'lib/canopus/debug/panel.rb', line 19

def watches
  @watches
end

Instance Method Details

#add_watch(expression) ⇒ Object

Raises:



84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/canopus/debug/panel.rb', line 84

def add_watch(expression)
  expression = watch_expression(expression)
  return false if @watches.include?(expression)
  raise Error, "too many watch expressions" if @watches.length >= WATCH_LIMIT

  @watches = [*@watches, expression].freeze
  token = @watch_tokens[expression] = Object.new.freeze
  @watch_results[expression] = @session && @selected_frame ? :loading : nil
  @tree.replace_children(ROOT_WATCHES, watch_nodes)
  evaluate_watch(expression, token) if @session && @selected_frame
  @request_frame.call
  true
end

#clear ⇒ Object



67
68
69
70
71
72
73
74
75
76
# File 'lib/canopus/debug/panel.rb', line 67

def clear
  reset_requests
  @session = @selected_frame = nil
  @stack_frames = [].freeze
  @watch_results = {}
  @tree.replace(nodes)
  restore_expansions
  @request_frame.call
  nil
end

#continued(session) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/canopus/debug/panel.rb', line 54

def continued(session)
  return false unless @session.equal?(session)

  reset_requests
  @session = @selected_frame = nil
  @stack_frames = [].freeze
  @watch_results = {}
  @tree.replace(nodes)
  restore_expansions
  @request_frame.call
  true
end

#refresh_breakpoints ⇒ Object



78
79
80
81
82
# File 'lib/canopus/debug/panel.rb', line 78

def refresh_breakpoints
  @tree.replace_children(ROOT_BREAKPOINTS, breakpoint_nodes)
  @request_frame.call
  nil
end

#remove_watch(expression) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/canopus/debug/panel.rb', line 98

def remove_watch(expression)
  replacement = @watches.reject { |item| item == expression }
  return false if replacement.length == @watches.length

  @watches = replacement.freeze
  @watch_tokens.delete(expression)
  @watch_results.delete(expression)
  @expanded_paths.delete_if { |path| path.first == :watch && path.dig(1, 0) == expression }
  @tree.replace_children(ROOT_WATCHES, watch_nodes)
  @request_frame.call
  true
end

#stopped(session, frame) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/canopus/debug/panel.rb', line 41

def stopped(session, frame)
  reset_requests
  @session, @selected_frame = session, frame
  @stack_frames = [frame].freeze
  @watch_results = @watches.to_h { |expression| [expression, :loading] }
  @tree.replace(nodes)
  restore_expansions
  request_stack
  evaluate_watches
  @request_frame.call
  self
end