Class: Canopus::Debug::Console

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

Constant Summary collapse

ITEM_LIMIT =
1_000
TEXT_LIMIT =
4_096
PENDING_LIMIT =
16
OUTPUT_QUEUE_LIMIT =
ITEM_LIMIT

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(post:, request_frame:) ⇒ Console

Returns a new instance of Console.

Raises:

  • (ArgumentError)


16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/canopus/debug/console.rb', line 16

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

  @post, @request_frame = post, request_frame
  @generation = @sequence = 0
  @pending = Set.new
  @output_lock = Mutex.new
  @output_generation = 0
  @output_queue = []
  @output_flush_pending = false
  @entries = [].freeze
  @tree = Zaniah::UI::TreeView.new(nodes, height: 320)
end

Instance Attribute Details

#entries ⇒ Object (readonly)

Returns the value of attribute entries.



14
15
16
# File 'lib/canopus/debug/console.rb', line 14

def entries
  @entries
end

#selected_frame ⇒ Object (readonly)

Returns the value of attribute selected_frame.



14
15
16
# File 'lib/canopus/debug/console.rb', line 14

def selected_frame
  @selected_frame
end

#tree ⇒ Object (readonly)

Returns the value of attribute tree.



14
15
16
# File 'lib/canopus/debug/console.rb', line 14

def tree
  @tree
end

Instance Method Details

#attach(session) ⇒ Object



30
31
32
33
34
35
36
37
# File 'lib/canopus/debug/console.rb', line 30

def attach(session)
  reset_requests
  reset_output(session)
  @selected_frame = nil
  @entries = [].freeze
  refresh
  self
end

#clear ⇒ Object



55
56
57
58
59
60
# File 'lib/canopus/debug/console.rb', line 55

def clear
  detach
  @entries = [].freeze
  refresh
  nil
end

#continued(session) ⇒ Object



47
48
49
50
51
52
53
# File 'lib/canopus/debug/console.rb', line 47

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

  reset_requests
  @selected_frame = nil
  true
end

#detach ⇒ Object



62
63
64
65
66
67
# File 'lib/canopus/debug/console.rb', line 62

def detach
  reset_requests
  reset_output(nil)
  @selected_frame = nil
  nil
end

#evaluate(expression) ⇒ Object

Raises:



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/canopus/debug/console.rb', line 91

def evaluate(expression)
  expression = checked_expression(expression)
  raise Error, "debug session is not stopped" unless active?
  raise Error, "too many pending debug evaluations" if @pending.length >= PENDING_LIMIT

  generation, session, frame = @generation, @session, @selected_frame
  append("> #{expression}")
  future = session.evaluate(expression, frame_id: frame.id, context: "repl")
  @pending.add(future)
  future.on_complete do |variable, error|
    @post.call do
      @pending.delete(future)
      next unless generation == @generation && @session.equal?(session) && @selected_frame.equal?(frame)

      if error
        append("Error: #{bounded_text(error.message)}")
      else
        append(result_label(variable))
      end
    end
  end
  future
end

#output(session, event) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/canopus/debug/console.rb', line 69

def output(session, event)
  return false unless output_session?(session)
  rows = output_rows(event)
  return false if rows.empty?

  schedule = false
  generation = @output_lock.synchronize do
    next unless @session.equal?(session)

    room = OUTPUT_QUEUE_LIMIT - @output_queue.length
    @output_queue.concat(rows.first(room)) if room.positive?
    unless @output_flush_pending
      @output_flush_pending = schedule = true
    end
    @output_generation
  end
  return false unless generation

  @post.call { flush_output(session, generation) } if schedule
  true
end

#stopped(session, frame) ⇒ Object



39
40
41
42
43
44
45
# File 'lib/canopus/debug/console.rb', line 39

def stopped(session, frame)
  return false unless @session.equal?(session)

  reset_requests
  @selected_frame = frame
  true
end