ruby_jard 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  3. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  4. data/.github/workflows/ruby.yml +85 -0
  5. data/.gitignore +1 -0
  6. data/.rubocop.yml +70 -1
  7. data/CHANGELOG.md +31 -0
  8. data/Gemfile +6 -3
  9. data/README.md +122 -8
  10. data/bin/console +1 -2
  11. data/docs/color_schemes/256-light.png +0 -0
  12. data/docs/color_schemes/gruvbox.png +0 -0
  13. data/docs/color_schemes/one-half-dark.png +0 -0
  14. data/docs/color_schemes/one-half-light.png +0 -0
  15. data/lib/ruby_jard.rb +5 -5
  16. data/lib/ruby_jard/box_drawer.rb +4 -1
  17. data/lib/ruby_jard/color_schemes.rb +31 -15
  18. data/lib/ruby_jard/color_schemes/256_color_scheme.rb +37 -37
  19. data/lib/ruby_jard/color_schemes/256_light_color_scheme.rb +62 -0
  20. data/lib/ruby_jard/color_schemes/deep_space_color_scheme.rb +36 -36
  21. data/lib/ruby_jard/color_schemes/gruvbox_color_scheme.rb +62 -0
  22. data/lib/ruby_jard/color_schemes/one_half_dark_color_scheme.rb +61 -0
  23. data/lib/ruby_jard/color_schemes/one_half_light_color_scheme.rb +62 -0
  24. data/lib/ruby_jard/column.rb +3 -1
  25. data/lib/ruby_jard/commands/continue_command.rb +2 -3
  26. data/lib/ruby_jard/commands/down_command.rb +9 -5
  27. data/lib/ruby_jard/commands/exit_command.rb +27 -0
  28. data/lib/ruby_jard/commands/frame_command.rb +11 -10
  29. data/lib/ruby_jard/commands/jard/color_scheme_command.rb +52 -0
  30. data/lib/ruby_jard/commands/jard/hide_command.rb +40 -0
  31. data/lib/ruby_jard/commands/jard/output_command.rb +28 -0
  32. data/lib/ruby_jard/commands/jard/show_command.rb +41 -0
  33. data/lib/ruby_jard/commands/jard_command.rb +50 -0
  34. data/lib/ruby_jard/commands/list_command.rb +5 -4
  35. data/lib/ruby_jard/commands/next_command.rb +10 -5
  36. data/lib/ruby_jard/commands/step_command.rb +10 -5
  37. data/lib/ruby_jard/commands/step_out_command.rb +10 -5
  38. data/lib/ruby_jard/commands/up_command.rb +10 -5
  39. data/lib/ruby_jard/commands/validation_helpers.rb +50 -0
  40. data/lib/ruby_jard/config.rb +7 -3
  41. data/lib/ruby_jard/console.rb +10 -22
  42. data/lib/ruby_jard/control_flow.rb +3 -3
  43. data/lib/ruby_jard/decorators/color_decorator.rb +11 -5
  44. data/lib/ruby_jard/decorators/loc_decorator.rb +1 -1
  45. data/lib/ruby_jard/decorators/path_decorator.rb +20 -7
  46. data/lib/ruby_jard/decorators/source_decorator.rb +2 -0
  47. data/lib/ruby_jard/frame.rb +55 -0
  48. data/lib/ruby_jard/keys.rb +0 -3
  49. data/lib/ruby_jard/layout.rb +9 -2
  50. data/lib/ruby_jard/layout_calculator.rb +29 -12
  51. data/lib/ruby_jard/layout_picker.rb +34 -0
  52. data/lib/ruby_jard/layouts.rb +52 -0
  53. data/lib/ruby_jard/layouts/narrow_horizontal_layout.rb +28 -0
  54. data/lib/ruby_jard/layouts/narrow_vertical_layout.rb +32 -0
  55. data/lib/ruby_jard/layouts/tiny_layout.rb +25 -0
  56. data/lib/ruby_jard/layouts/wide_layout.rb +13 -15
  57. data/lib/ruby_jard/pager.rb +96 -0
  58. data/lib/ruby_jard/repl_processor.rb +61 -31
  59. data/lib/ruby_jard/repl_proxy.rb +193 -89
  60. data/lib/ruby_jard/row.rb +16 -1
  61. data/lib/ruby_jard/row_renderer.rb +51 -42
  62. data/lib/ruby_jard/screen.rb +2 -12
  63. data/lib/ruby_jard/screen_adjuster.rb +104 -0
  64. data/lib/ruby_jard/screen_drawer.rb +3 -0
  65. data/lib/ruby_jard/screen_manager.rb +32 -54
  66. data/lib/ruby_jard/screen_renderer.rb +30 -16
  67. data/lib/ruby_jard/screens.rb +31 -12
  68. data/lib/ruby_jard/screens/backtrace_screen.rb +23 -26
  69. data/lib/ruby_jard/screens/menu_screen.rb +53 -22
  70. data/lib/ruby_jard/screens/source_screen.rb +65 -37
  71. data/lib/ruby_jard/screens/threads_screen.rb +14 -14
  72. data/lib/ruby_jard/screens/variables_screen.rb +59 -34
  73. data/lib/ruby_jard/session.rb +19 -10
  74. data/lib/ruby_jard/span.rb +3 -0
  75. data/lib/ruby_jard/templates/layout_template.rb +1 -1
  76. data/lib/ruby_jard/templates/screen_template.rb +3 -4
  77. data/lib/ruby_jard/version.rb +1 -1
  78. data/ruby_jard.gemspec +1 -1
  79. metadata +38 -9
  80. data/lib/ruby_jard/commands/color_scheme_command.rb +0 -42
  81. data/lib/ruby_jard/layouts/narrow_layout.rb +0 -41
  82. data/lib/ruby_jard/screens/empty_screen.rb +0 -13
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # rubocop:disable Metrics/MethodLength
4
- # rubocop:disable Metrics/CyclomaticComplexity
5
4
  module RubyJard
6
5
  ##
7
6
  # Layout calculator based on screen resolution to decide the height, width,
@@ -12,27 +11,31 @@ module RubyJard
12
11
  new(**args).calculate
13
12
  end
14
13
 
15
- def initialize(layout_template:, width: 0, height: 0, x: 0, y: 0)
14
+ def initialize(
15
+ layout_template:, width: 0, height: 0, x: 0, y: 0,
16
+ config: RubyJard.config
17
+ )
16
18
  @layout_template = layout_template
17
19
  @width = width
18
20
  @height = height
19
21
  @x = x
20
22
  @y = y
21
23
  @layouts = []
24
+ @config = config
22
25
  end
23
26
 
24
27
  def calculate
25
28
  @layouts = []
26
- calculate_layout(@layout_template, @width, @height, @x, @y)
29
+ calculate_layout(@layout_template, @width, @height, @x, @y, nil)
27
30
  @layouts
28
31
  end
29
32
 
30
33
  private
31
34
 
32
- def calculate_layout(template, width, height, x, y)
35
+ def calculate_layout(template, width, height, x, y, parent_template)
33
36
  if template.is_a?(RubyJard::Templates::ScreenTemplate)
34
37
  layout = RubyJard::Layout.new(
35
- template: template,
38
+ template: template, parent_template: parent_template,
36
39
  width: width - 2, height: height - 2, x: x + 1, y: y + 1,
37
40
  box_width: width, box_height: height, box_x: x, box_y: y
38
41
  )
@@ -45,7 +48,7 @@ module RubyJard
45
48
  max_height = 0
46
49
 
47
50
  lines = [[]]
48
- template.children.each do |child_template|
51
+ visible_children(template).each do |child_template|
49
52
  child_height = calculate_child_height(child_template, height)
50
53
  child_width = calculate_child_width(child_template, width)
51
54
 
@@ -57,23 +60,37 @@ module RubyJard
57
60
  overflow_width = 0
58
61
  max_height = child_height
59
62
  lines << []
60
- else
61
- max_height = child_height if max_height < child_height
63
+ elsif max_height < child_height
64
+ max_height = child_height
62
65
  end
63
66
 
64
67
  lines.last << [child_template, child_width, child_height, child_x, child_y]
65
68
  child_x += child_width
66
69
  end
67
70
 
68
- stretch_lines(template, width, height, lines)
71
+ stretch_children_layouts(template, width, height, lines)
69
72
  lines.each do |line|
70
73
  line.each do |child_template, child_width, child_height, xx, yy|
71
- calculate_layout(child_template, child_width, child_height, xx, yy)
74
+ calculate_layout(child_template, child_width, child_height, xx, yy, template)
72
75
  end
73
76
  end
74
77
  end
75
78
  end
76
79
 
80
+ def visible_children(template)
81
+ template.children.select do |child|
82
+ visible?(child)
83
+ end
84
+ end
85
+
86
+ def visible?(template)
87
+ if template.is_a?(RubyJard::Templates::ScreenTemplate)
88
+ @config.enabled_screens.include?(template.screen.to_s.strip)
89
+ else
90
+ template.children.any? { |child| visible?(child) }
91
+ end
92
+ end
93
+
77
94
  def adjust_layout_overlap(layout)
78
95
  if layout.box_x != 0
79
96
  layout.width += 1
@@ -90,7 +107,8 @@ module RubyJard
90
107
  end
91
108
  end
92
109
 
93
- def stretch_lines(parent_template, parent_width, parent_height, lines)
110
+ # Stretch the children layouts to fill the gaps, remove redundant spaces inside the parent layout
111
+ def stretch_children_layouts(parent_template, parent_width, parent_height, lines)
94
112
  total_height = 0
95
113
  lines.each_with_index do |line, line_index|
96
114
  desired_height =
@@ -148,4 +166,3 @@ module RubyJard
148
166
  end
149
167
 
150
168
  # rubocop:enable Metrics/MethodLength
151
- # rubocop:enable Metrics/CyclomaticComplexity
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyJard
4
+ ##
5
+ # Pick layout smartly depending on current window height and width
6
+ class LayoutPicker
7
+ def initialize(width, height, layouts: RubyJard::Layouts, config: RubyJard.config)
8
+ @width = width
9
+ @height = height
10
+ @layouts = layouts
11
+ @config = config
12
+ end
13
+
14
+ def pick
15
+ unless @config.layout.nil?
16
+ return @layouts[@config.layout] || @layouts.fallback_layout
17
+ end
18
+
19
+ @layouts.each do |_name, template|
20
+ matched = true
21
+ matched &&= (
22
+ template.min_width.nil? ||
23
+ @width > template.min_width
24
+ )
25
+ matched &&= (
26
+ template.min_height.nil? ||
27
+ @height > template.min_height
28
+ )
29
+ return template if matched
30
+ end
31
+ @layouts.fallback_layout
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ruby_jard/layout'
4
+ require 'ruby_jard/templates/layout_template'
5
+ require 'ruby_jard/templates/screen_template'
6
+ require 'ruby_jard/layout_picker'
7
+ require 'ruby_jard/layout_calculator'
8
+
9
+ module RubyJard
10
+ ##
11
+ # Layouts registry.
12
+ class Layouts
13
+ class << self
14
+ extend Forwardable
15
+ def_delegators :instance, :fallback_layout, :add_layout, :[], :get, :each
16
+
17
+ def instance
18
+ @instance ||= new
19
+ end
20
+ end
21
+
22
+ attr_reader :fallback_layout
23
+
24
+ def initialize(fallback_layout = RubyJard::Layouts::WideLayout)
25
+ @layout_registry = {}
26
+ @fallback_layout = fallback_layout
27
+ end
28
+
29
+ def add_layout(name, layout_class)
30
+ unless layout_class.is_a?(RubyJard::Templates::LayoutTemplate)
31
+ raise RubyJard::Error, "#{layout_class} must be a #{RubyJard::Templates::LayoutTemplate}"
32
+ end
33
+
34
+ @layout_registry[name] = layout_class
35
+ end
36
+
37
+ def [](name)
38
+ @layout_registry[name.to_s.strip]
39
+ end
40
+ alias_method :get, :[]
41
+
42
+ def each(&block)
43
+ @layout_registry.each(&block)
44
+ end
45
+ end
46
+ end
47
+
48
+ # Registering order is also priority when picking layout
49
+ require 'ruby_jard/layouts/wide_layout'
50
+ require 'ruby_jard/layouts/narrow_vertical_layout'
51
+ require 'ruby_jard/layouts/narrow_horizontal_layout'
52
+ require 'ruby_jard/layouts/tiny_layout'
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyJard
4
+ class Layouts
5
+ NarrowHorizontalLayout = RubyJard::Templates::LayoutTemplate.new(
6
+ min_width: 80,
7
+ min_height: 10,
8
+ fill_height: false,
9
+ children: [
10
+ RubyJard::Templates::LayoutTemplate.new(
11
+ height_ratio: 80,
12
+ width_ratio: 100,
13
+ children: [
14
+ RubyJard::Templates::ScreenTemplate.new(
15
+ screen: :source,
16
+ width_ratio: 60
17
+ ),
18
+ RubyJard::Templates::ScreenTemplate.new(
19
+ screen: :variables,
20
+ width_ratio: 40
21
+ )
22
+ ]
23
+ )
24
+ ]
25
+ )
26
+ end
27
+ end
28
+ RubyJard::Layouts.add_layout('narrow-horizontal', RubyJard::Layouts::NarrowHorizontalLayout)
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyJard
4
+ class Layouts
5
+ NarrowVerticalLayout = RubyJard::Templates::LayoutTemplate.new(
6
+ min_width: 40,
7
+ min_height: 24,
8
+ fill_height: false,
9
+ children: [
10
+ RubyJard::Templates::LayoutTemplate.new(
11
+ height_ratio: 80,
12
+ width_ratio: 100,
13
+ children: [
14
+ RubyJard::Templates::ScreenTemplate.new(
15
+ screen: :source,
16
+ height_ratio: 60
17
+ ),
18
+ RubyJard::Templates::ScreenTemplate.new(
19
+ screen: :variables,
20
+ height_ratio: 40
21
+ )
22
+ ]
23
+ ),
24
+ RubyJard::Templates::ScreenTemplate.new(
25
+ height: 2,
26
+ screen: :menu
27
+ )
28
+ ]
29
+ )
30
+ end
31
+ end
32
+ RubyJard::Layouts.add_layout('narrow-vertical', RubyJard::Layouts::NarrowVerticalLayout)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyJard
4
+ class Layouts
5
+ TinyLayout = RubyJard::Templates::LayoutTemplate.new(
6
+ min_height: 10,
7
+ fill_height: false,
8
+ children: [
9
+ RubyJard::Templates::LayoutTemplate.new(
10
+ height_ratio: 80,
11
+ width_ratio: 100,
12
+ min_height: 7,
13
+ fill_height: true,
14
+ children: [
15
+ RubyJard::Templates::ScreenTemplate.new(
16
+ screen: :source,
17
+ height_ratio: 100
18
+ )
19
+ ]
20
+ )
21
+ ]
22
+ )
23
+ end
24
+ end
25
+ RubyJard::Layouts.add_layout('tiny', RubyJard::Layouts::TinyLayout)
@@ -1,26 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyJard
4
- module Layouts
4
+ class Layouts
5
5
  WideLayout = RubyJard::Templates::LayoutTemplate.new(
6
6
  min_width: 120,
7
- min_height: 10,
8
- fill_width: true,
7
+ min_height: 24,
8
+ fill_height: false,
9
9
  children: [
10
10
  RubyJard::Templates::LayoutTemplate.new(
11
11
  height_ratio: 80,
12
12
  width_ratio: 50,
13
- min_height: 7,
14
- fill_height: true,
15
13
  children: [
16
14
  RubyJard::Templates::ScreenTemplate.new(
17
15
  screen: :source,
18
- height_ratio: 60
16
+ height_ratio: 70,
17
+ adjust_mode: :expand
19
18
  ),
20
19
  RubyJard::Templates::ScreenTemplate.new(
21
- screen: :variables,
22
- width_ratio: 100,
23
- height_ratio: 40,
20
+ screen: :backtrace,
21
+ height_ratio: 30,
24
22
  min_height: 3
25
23
  )
26
24
  ]
@@ -28,17 +26,16 @@ module RubyJard
28
26
  RubyJard::Templates::LayoutTemplate.new(
29
27
  height_ratio: 80,
30
28
  width_ratio: 50,
31
- fill_height: true,
32
29
  children: [
33
30
  RubyJard::Templates::ScreenTemplate.new(
34
- screen: :backtrace,
35
- height_ratio: 50,
36
- fill_height: true
31
+ screen: :variables,
32
+ height_ratio: 80,
33
+ adjust_mode: :expand
37
34
  ),
38
35
  RubyJard::Templates::ScreenTemplate.new(
39
36
  screen: :threads,
40
- height_ratio: 50,
41
- fill_height: true
37
+ height_ratio: 20,
38
+ min_height: 3
42
39
  )
43
40
  ]
44
41
  ),
@@ -50,3 +47,4 @@ module RubyJard
50
47
  )
51
48
  end
52
49
  end
50
+ RubyJard::Layouts.add_layout('wide', RubyJard::Layouts::WideLayout)
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyJard
4
+ ##
5
+ # Override Pry's pager system. Again, Pry doesn't support customizing pager. So...
6
+ class Pager
7
+ def initialize(pry_instance)
8
+ @pry_instance = pry_instance
9
+ end
10
+
11
+ def page(text)
12
+ open do |pager|
13
+ pager << text
14
+ end
15
+ end
16
+
17
+ def open(options = {})
18
+ pager = LessPager.new(@pry_instance, **options)
19
+ yield pager
20
+ rescue Pry::Pager::StopPaging
21
+ # Ignore
22
+ ensure
23
+ pager.close
24
+ end
25
+
26
+ private
27
+
28
+ def enabled?
29
+ !!@enabled
30
+ end
31
+
32
+ ##
33
+ # Pager using GNU Less
34
+ class LessPager < Pry::Pager::NullPager
35
+ def initialize(pry_instance, force_open: false, pager_start_at_the_end: false)
36
+ super(pry_instance.output)
37
+ @pry_instance = pry_instance
38
+ @buffer = ''
39
+
40
+ @pager_start_at_the_end = pager_start_at_the_end
41
+
42
+ @tracker = Pry::Pager::PageTracker.new(height, width)
43
+ @pager = force_open ? open_pager : nil
44
+ end
45
+
46
+ def write(str)
47
+ if invoked_pager?
48
+ write_into_pager str
49
+ else
50
+ @tracker.record str
51
+ @buffer += str
52
+ if @tracker.page?
53
+ @pager = open_pager
54
+ write_into_pager(@buffer)
55
+ end
56
+ end
57
+ rescue Errno::EPIPE
58
+ raise Pry::Pager::StopPaging
59
+ end
60
+
61
+ def close
62
+ if invoked_pager?
63
+ @pager.close
64
+ @pry_instance.exec_hook :after_pager, self
65
+
66
+ prompt = @pry_instance.prompt.wait_proc.call
67
+ # TODO: should show this tip even pager not invoked, when the size exceed a certain height
68
+ @out.puts "#{prompt}Tips: You can use `list` command to show back debugger screens"
69
+ else
70
+ @out.write @buffer
71
+ end
72
+ end
73
+
74
+ def invoked_pager?
75
+ @pager
76
+ end
77
+
78
+ def open_pager
79
+ @pry_instance.exec_hook :before_pager, self
80
+ less_command = ['less', '-R', '-X']
81
+ less_command << '+G' if @pager_start_at_the_end
82
+
83
+ IO.popen(
84
+ less_command.join(' '), 'w',
85
+ out: @pry_instance.output, err: @pry_instance.output
86
+ )
87
+ end
88
+
89
+ def write_into_pager(str)
90
+ return unless invoked_pager?
91
+
92
+ @pager.write str.encode('UTF-8', undef: :replace)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,5 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'ruby_jard/commands/validation_helpers'
4
+ require 'ruby_jard/commands/continue_command'
5
+ require 'ruby_jard/commands/exit_command'
6
+ require 'ruby_jard/commands/up_command'
7
+ require 'ruby_jard/commands/down_command'
8
+ require 'ruby_jard/commands/next_command'
9
+ require 'ruby_jard/commands/step_command'
10
+ require 'ruby_jard/commands/step_out_command'
11
+ require 'ruby_jard/commands/frame_command'
12
+ require 'ruby_jard/commands/list_command'
13
+ require 'ruby_jard/commands/jard_command'
14
+
3
15
  module RubyJard
4
16
  ##
5
17
  # Byebug allows customizing processor with a series of hooks (https://github.com/deivid-rodriguez/byebug/blob/e1fb8209d56922f7bafd128af84e61568b6cd6a7/lib/byebug/processors/command_processor.rb)
@@ -10,8 +22,8 @@ module RubyJard
10
22
  # repl, and triggers Byebug debugger if needed.
11
23
  #
12
24
  class ReplProcessor < Byebug::CommandProcessor
13
- def initialize(context, interface = LocalInterface.new)
14
- super(context, interface)
25
+ def initialize(context, *args)
26
+ super(context, *args)
15
27
  @repl_proxy = RubyJard::ReplProxy.new(
16
28
  key_bindings: RubyJard.global_key_bindings
17
29
  )
@@ -21,7 +33,7 @@ module RubyJard
21
33
  process_commands_with_lock
22
34
  end
23
35
 
24
- def at_return(_)
36
+ def at_return(_return_value)
25
37
  process_commands_with_lock
26
38
  end
27
39
 
@@ -61,44 +73,39 @@ module RubyJard
61
73
  raise
62
74
  end
63
75
 
64
- def handle_next_command(_options = {})
65
- Byebug.current_context.step_over(1, Byebug.current_context.frame.pos)
76
+ def handle_next_command(options = {})
77
+ times = options[:times] || 1
78
+ Byebug.current_context.step_over(times, Byebug.current_context.frame.pos)
66
79
  proceed!
67
80
  end
68
81
 
69
- def handle_step_command(_options = {})
70
- Byebug.current_context.step_into(1, Byebug.current_context.frame.pos)
82
+ def handle_step_command(options = {})
83
+ times = options[:times] || 1
84
+ Byebug.current_context.step_into(times, Byebug.current_context.frame.pos)
71
85
  proceed!
72
86
  end
73
87
 
74
- def handle_step_out_command(_options = {})
75
- # TODO: handle c-frame and out of range frames
76
- Byebug.current_context.frame = 1
77
- proceed!
88
+ def handle_step_out_command(options = {})
89
+ times = options[:times] || 1
90
+
91
+ next_frame = up_n_frames(Byebug.current_context.frame.pos, times)
92
+ Byebug.current_context.frame = next_frame
78
93
  Byebug.current_context.step_over(1, Byebug.current_context.frame.pos)
79
94
  proceed!
80
95
  end
81
96
 
82
- def handle_up_command(_options = {})
83
- next_frame = [
84
- Byebug.current_context.frame.pos + 1,
85
- Byebug.current_context.backtrace.length - 1
86
- ].min
87
- while Byebug::Frame.new(Byebug.current_context, next_frame).c_frame? &&
88
- next_frame < Byebug.current_context.backtrace.length - 1
89
- next_frame += 1
90
- end
97
+ def handle_up_command(options = {})
98
+ times = options[:times] || 1
99
+
100
+ next_frame = up_n_frames(Byebug.current_context.frame.pos, times)
91
101
  Byebug.current_context.frame = next_frame
92
102
  proceed!
93
103
  process_commands
94
104
  end
95
105
 
96
- def handle_down_command(_options = {})
97
- next_frame = [Byebug.current_context.frame.pos - 1, 0].max
98
- while Byebug::Frame.new(Byebug.current_context, next_frame).c_frame? &&
99
- next_frame > 0
100
- next_frame -= 1
101
- end
106
+ def handle_down_command(options = {})
107
+ times = options[:times] || 1
108
+ next_frame = down_n_frames(Byebug.current_context.frame.pos, times)
102
109
  Byebug.current_context.frame = next_frame
103
110
  proceed!
104
111
  process_commands
@@ -107,7 +114,7 @@ module RubyJard
107
114
  def handle_frame_command(options)
108
115
  next_frame = options[:frame].to_i
109
116
  if Byebug::Frame.new(Byebug.current_context, next_frame).c_frame?
110
- puts "Error: Frame #{next_frame} is a c-frame. Not able to inspect c layer!"
117
+ RubyJard::ScreenManager.puts "Error: Frame #{next_frame} is a c-frame. Not able to inspect c layer!"
111
118
  process_commands(false)
112
119
  else
113
120
  Byebug.current_context.frame = next_frame
@@ -117,7 +124,11 @@ module RubyJard
117
124
  end
118
125
 
119
126
  def handle_continue_command(_options = {})
120
- # Do nothing
127
+ RubyJard::ScreenManager.puts '► ► Program resumed ► ►'
128
+ end
129
+
130
+ def handle_exit_command(_options = {})
131
+ Kernel.exit
121
132
  end
122
133
 
123
134
  def handle_key_binding_command(options = {})
@@ -134,9 +145,28 @@ module RubyJard
134
145
  process_commands
135
146
  end
136
147
 
137
- def handle_color_scheme_command(options = {})
138
- RubyJard.config.color_scheme = options[:color_scheme]
139
- process_commands
148
+ def up_n_frames(current_frame, times)
149
+ next_frame = current_frame
150
+ times.times do
151
+ next_frame = [next_frame + 1, Byebug.current_context.backtrace.length - 1].min
152
+ while Byebug::Frame.new(Byebug.current_context, next_frame).c_frame? &&
153
+ next_frame < Byebug.current_context.backtrace.length - 1
154
+ next_frame += 1
155
+ end
156
+ end
157
+ next_frame
158
+ end
159
+
160
+ def down_n_frames(current_frame, times)
161
+ next_frame = current_frame
162
+ times.times do
163
+ next_frame = [next_frame - 1, 0].max
164
+ while Byebug::Frame.new(Byebug.current_context, next_frame).c_frame? &&
165
+ next_frame > 0
166
+ next_frame -= 1
167
+ end
168
+ end
169
+ next_frame
140
170
  end
141
171
  end
142
172
  end