ruby_jard 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyJard
4
- module Screens
4
+ class Screens
5
5
  ##
6
6
  # Backtrace screen implements the content to display current thread's backtrace to the user.
7
7
  class BacktraceScreen < RubyJard::Screen
@@ -10,7 +10,7 @@ module RubyJard
10
10
  end
11
11
 
12
12
  def build
13
- @rows = @session.backtrace.map.with_index do |frame, frame_id|
13
+ @rows = @session.current_backtrace.map.with_index do |frame, frame_id|
14
14
  RubyJard::Row.new(
15
15
  line_limit: 2,
16
16
  columns: [
@@ -39,36 +39,35 @@ module RubyJard
39
39
  frame_id_label = frame_id.to_s.rjust(frames_count.to_s.length)
40
40
  if current_frame?(frame_id)
41
41
  RubyJard::Span.new(
42
- content: frame_id_label,
42
+ content: "➠ #{frame_id_label}",
43
43
  styles: :frame_id_highlighted
44
44
  )
45
45
  else
46
46
  RubyJard::Span.new(
47
- content: frame_id_label,
47
+ content: " #{frame_id_label}",
48
48
  styles: :frame_id
49
49
  )
50
50
  end
51
51
  end
52
52
 
53
53
  def span_class_label(frame)
54
- object = frame[1]
55
- klass = frame[2]
56
- klass_label =
57
- if klass.nil? || object.class == klass
58
- if object.is_a?(Class)
59
- object.name
54
+ class_label =
55
+ if frame.frame_class.nil? || frame.frame_self.class == frame.frame_class
56
+ if frame.frame_self.is_a?(Class)
57
+ frame.frame_self.name
60
58
  else
61
- object.class.name
59
+ frame.frame_self.class.name
62
60
  end
63
- elsif klass.singleton_class?
61
+ elsif frame.frame_class.singleton_class?
64
62
  # No easy way to get the original class of a singleton class
65
- object.respond_to?(:name) ? object.name : object.to_s
63
+ frame.frame_self.respond_to?(:name) ? frame.frame_self.name : frame.frame_self.to_s
66
64
  else
67
- klass.name
65
+ frame.frame_class.name
68
66
  end
69
- c_frame = frame.last.nil? ? '[c] ' : ''
67
+
68
+ c_frame = frame.c_frame? ? '[c] ' : ''
70
69
  RubyJard::Span.new(
71
- content: "#{c_frame}#{klass_label}",
70
+ content: "#{c_frame}#{class_label}",
72
71
  margin_right: 1,
73
72
  styles: :constant
74
73
  )
@@ -83,12 +82,11 @@ module RubyJard
83
82
  end
84
83
 
85
84
  def span_method_label(frame)
86
- location = frame[0]
87
85
  method_label =
88
- if location.label != location.base_label
89
- "#{location.base_label} (#{location.label.split(' ').first})"
86
+ if frame.frame_location.label != frame.frame_location.base_label
87
+ "#{frame.frame_location.base_label} (#{frame.frame_location.label.split(' ').first})"
90
88
  else
91
- location.base_label
89
+ frame.frame_location.base_label
92
90
  end
93
91
  RubyJard::Span.new(
94
92
  content: method_label,
@@ -98,8 +96,7 @@ module RubyJard
98
96
  end
99
97
 
100
98
  def span_path(frame)
101
- location = frame[0]
102
- decorated_path = decorate_path(location.absolute_path, location.lineno)
99
+ decorated_path = decorate_path(frame.frame_location.absolute_path, frame.frame_location.lineno)
103
100
 
104
101
  path_label =
105
102
  if decorated_path.gem?
@@ -118,15 +115,15 @@ module RubyJard
118
115
  end
119
116
 
120
117
  def current_frame
121
- if @session.frame.nil?
118
+ if @session.current_frame.nil?
122
119
  0
123
120
  else
124
- @session.frame.pos.to_i
121
+ @session.current_frame.pos.to_i
125
122
  end
126
123
  end
127
124
 
128
125
  def frames_count
129
- @session.backtrace.length
126
+ @session.current_backtrace.length
130
127
  end
131
128
 
132
129
  def decorate_path(path, lineno)
@@ -136,4 +133,4 @@ module RubyJard
136
133
  end
137
134
  end
138
135
 
139
- RubyJard::Screens.add_screen(:backtrace, RubyJard::Screens::BacktraceScreen)
136
+ RubyJard::Screens.add_screen('backtrace', RubyJard::Screens::BacktraceScreen)
@@ -1,32 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyJard
4
- module Screens
4
+ class Screens
5
+ ##
6
+ # Display key binding guidelines and shortcuts.
5
7
  class MenuScreen < RubyJard::Screen
6
8
  def build
7
- span_title = RubyJard::Span.new(
8
- content: ' REPL Console ',
9
- styles: :title_highlighted
10
- )
11
- menu_spans = generate_menu_spans
12
-
13
- alignment =
14
- @layout.width -
15
- span_title.content_length -
16
- menu_spans.map(&:content_length).sum
17
- span_align = RubyJard::Span.new(
18
- content: ' ' * (alignment < 0 ? 0 : alignment),
19
- styles: :background
20
- )
9
+ left_spans = generate_left_spans
10
+ right_spans = generate_right_spans
21
11
  @rows = [RubyJard::Row.new(
22
12
  line_limit: 1,
23
- ellipsis: false,
24
13
  columns: [
25
14
  RubyJard::Column.new(
15
+ word_wrap: RubyJard::Column::WORD_WRAP_BREAK_WORD,
26
16
  spans: [
27
- span_title,
28
- span_align,
29
- menu_spans
17
+ left_spans,
18
+ align(left_spans, right_spans),
19
+ right_spans
30
20
  ].flatten
31
21
  )
32
22
  ]
@@ -36,7 +26,37 @@ module RubyJard
36
26
 
37
27
  private
38
28
 
39
- def generate_menu_spans
29
+ def generate_left_spans
30
+ [
31
+ RubyJard::Span.new(
32
+ content: ' REPL ',
33
+ styles: :title_highlighted
34
+ )
35
+ ]
36
+ # [
37
+ # RubyJard::Span.new(
38
+ # content: ' Mode (F2) ',
39
+ # styles: :title_highlighted
40
+ # ),
41
+ # RubyJard::Span.new(
42
+ # margin_left: 1,
43
+ # content: 'All gems',
44
+ # styles: :menu_mode
45
+ # ),
46
+ # RubyJard::Span.new(
47
+ # margin_left: 1,
48
+ # content: '|',
49
+ # styles: :menu_tips
50
+ # ),
51
+ # RubyJard::Span.new(
52
+ # margin_left: 1,
53
+ # content: 'Application only',
54
+ # styles: :menu_tips
55
+ # )
56
+ # ]
57
+ end
58
+
59
+ def generate_right_spans
40
60
  [
41
61
  'Up (F6)',
42
62
  'Down (Shift+F6)',
@@ -48,12 +68,23 @@ module RubyJard
48
68
  RubyJard::Span.new(
49
69
  content: menu_item,
50
70
  margin_left: 3,
51
- styles: :control_buttons
71
+ styles: :menu_tips
52
72
  )
53
73
  end
54
74
  end
75
+
76
+ def align(left_spans, right_spans)
77
+ alignment =
78
+ @layout.width -
79
+ right_spans.map(&:content_length).sum -
80
+ left_spans.map(&:content_length).sum
81
+ RubyJard::Span.new(
82
+ content: ' ' * (alignment < 0 ? 0 : alignment),
83
+ styles: :background
84
+ )
85
+ end
55
86
  end
56
87
  end
57
88
  end
58
89
 
59
- RubyJard::Screens.add_screen(:menu, RubyJard::Screens::MenuScreen)
90
+ RubyJard::Screens.add_screen('menu', RubyJard::Screens::MenuScreen)
@@ -1,12 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyJard
4
- module Screens
4
+ class Screens
5
+ ##
6
+ # Display source code of current stopping line and surrounding lines
5
7
  class SourceScreen < RubyJard::Screen
8
+ ANONYMOUS_SIGNATURES = [
9
+ '(eval)', '-e'
10
+ ].freeze
11
+
6
12
  def title
7
- return 'Source' if RubyJard.current_session.frame.nil?
13
+ return 'Source' if @session.current_frame.nil?
8
14
 
9
- decorated_path = path_decorator(current_file, current_line)
15
+ decorated_path = path_decorator(@session.current_frame.frame_file, @session.current_frame.frame_line)
10
16
  if decorated_path.gem?
11
17
  ['Source', "#{decorated_path.gem} - #{decorated_path.path}:#{decorated_path.lineno}"]
12
18
  else
@@ -15,35 +21,73 @@ module RubyJard
15
21
  end
16
22
 
17
23
  def build
18
- return if RubyJard.current_session.frame.nil?
24
+ return if @session.current_frame.nil?
25
+
26
+ if ANONYMOUS_SIGNATURES.include? @session.current_frame.frame_file
27
+ # (eval) is hard-coded in Ruby source code for in-code evaluation
28
+ handle_anonymous_evaluation
29
+ else
30
+ # TODO: screen now supports window.
31
+ codes = source_decorator.codes
32
+ @rows = codes.map.with_index do |loc, index|
33
+ RubyJard::Row.new(
34
+ line_limit: 3,
35
+ columns: [
36
+ RubyJard::Column.new(
37
+ spans: [
38
+ span_mark(index),
39
+ span_lineno(index)
40
+ ]
41
+ ),
42
+ RubyJard::Column.new(
43
+ word_wrap: RubyJard::Column::WORD_WRAP_BREAK_WORD,
44
+ spans: loc_spans(loc)
45
+ )
46
+ ]
47
+ )
48
+ end
49
+ end
50
+ @selected = 0
51
+ end
52
+
53
+ private
19
54
 
20
- # TODO: screen now supports window.
21
- codes = source_decorator.codes
22
- @rows = codes.map.with_index do |loc, index|
55
+ def handle_anonymous_evaluation
56
+ @rows = [
23
57
  RubyJard::Row.new(
24
58
  line_limit: 3,
25
59
  columns: [
26
60
  RubyJard::Column.new(
27
61
  spans: [
28
- span_mark(index),
29
- span_lineno(index)
62
+ RubyJard::Span.new(
63
+ content: 'This section is anonymous!',
64
+ styles: :normal_token
65
+ )
30
66
  ]
31
- ),
67
+ )
68
+ ]
69
+ ),
70
+ RubyJard::Row.new(
71
+ line_limit: 3,
72
+ columns: [
32
73
  RubyJard::Column.new(
33
- word_wrap: RubyJard::Column::WORD_WRAP_BREAK_WORD,
34
- spans: loc_spans(loc)
74
+ spans: [
75
+ RubyJard::Span.new(
76
+ content: 'Maybe it is dynamically evaluated, or called via ruby-e, without file information.',
77
+ styles: :source_lineno
78
+ )
79
+ ]
35
80
  )
36
81
  ]
37
82
  )
38
- end
39
- @selected = 0
83
+ ]
40
84
  end
41
85
 
42
86
  def span_mark(index)
43
87
  lineno = source_lineno(index)
44
88
  RubyJard::Span.new(
45
89
  margin_right: 1,
46
- content: current_line == lineno ? '➠' : ' ',
90
+ content: @session.current_frame.frame_line == lineno ? '➠' : ' ',
47
91
  styles: :source_line_mark
48
92
  )
49
93
  end
@@ -52,39 +96,23 @@ module RubyJard
52
96
  lineno = source_lineno(index).to_s.rjust(source_decorator.window_end.to_s.length)
53
97
  RubyJard::Span.new(
54
98
  content: lineno,
55
- styles: current_line == lineno ? :source_line_mark : :source_lineno
99
+ styles: @session.current_frame.frame_line == lineno ? :source_line_mark : :source_lineno
56
100
  )
57
101
  end
58
102
 
59
103
  def loc_spans(loc)
60
- spans, _tokens = loc_decorator.decorate(loc, current_file)
104
+ spans, _tokens = loc_decorator.decorate(loc, @session.current_frame.frame_file)
61
105
  spans
62
106
  end
63
107
 
64
- private
65
-
66
- def current_binding
67
- RubyJard.current_session.frame._binding
68
- end
69
-
70
- def current_frame_scope
71
- RubyJard.current_session.backtrace[RubyJard.current_session.frame.pos][1]
72
- end
73
-
74
- def current_file
75
- RubyJard.current_session.frame.file
76
- end
77
-
78
- def current_line
79
- RubyJard.current_session.frame.line
80
- end
81
-
82
108
  def path_decorator(path, lineno)
83
109
  @path_decorator ||= RubyJard::Decorators::PathDecorator.new(path, lineno)
84
110
  end
85
111
 
86
112
  def source_decorator
87
- @source_decorator ||= RubyJard::Decorators::SourceDecorator.new(current_file, current_line, @layout.height)
113
+ @source_decorator ||= RubyJard::Decorators::SourceDecorator.new(
114
+ @session.current_frame.frame_file, @session.current_frame.frame_line, @layout.height
115
+ )
88
116
  end
89
117
 
90
118
  def loc_decorator
@@ -98,4 +126,4 @@ module RubyJard
98
126
  end
99
127
  end
100
128
 
101
- RubyJard::Screens.add_screen(:source, RubyJard::Screens::SourceScreen)
129
+ RubyJard::Screens.add_screen('source', RubyJard::Screens::SourceScreen)
@@ -1,14 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RubyJard
4
- module Screens
4
+ class Screens
5
+ ##
6
+ # Display all current alive threads, excluding internal threads
5
7
  class ThreadsScreen < RubyJard::Screen
6
8
  def title
7
- ['Threads', "#{RubyJard.current_session.contexts.length} threads"]
9
+ ['Threads', "#{@session.threads.length} threads"]
8
10
  end
9
11
 
10
12
  def build
11
- contexts = RubyJard.current_session.contexts.select { |c| c.thread.alive? }
13
+ contexts = @session.threads.select { |c| c.thread.alive? }
12
14
  contexts = sort_contexts(contexts)
13
15
  @rows = contexts.map do |context|
14
16
  RubyJard::Row.new(
@@ -40,10 +42,11 @@ module RubyJard
40
42
  private
41
43
 
42
44
  def span_mark(context)
45
+ style = thread_status_style(context.thread)
43
46
  RubyJard::Span.new(
44
47
  margin_right: 1,
45
- content: '•',
46
- styles: thread_status_style(context.thread)
48
+ content: style == :thread_status_run ? '►' : '•',
49
+ styles: style
47
50
  )
48
51
  end
49
52
 
@@ -72,11 +75,11 @@ module RubyJard
72
75
  def span_thread_location(context)
73
76
  return unknown_thread_location if
74
77
  context.thread.backtrace_locations.nil? ||
75
- RubyJard.current_session.backtrace[0].nil?
78
+ @session.current_frame.frame_location.nil?
76
79
 
77
80
  last_backtrace =
78
81
  if current_thread?(context)
79
- RubyJard.current_session.backtrace[0].first
82
+ @session.current_frame.frame_location
80
83
  else
81
84
  context.thread.backtrace_locations[1]
82
85
  end
@@ -112,14 +115,10 @@ module RubyJard
112
115
  contexts.sort do |a, b|
113
116
  [
114
117
  bool_to_int(current_thread?(a)),
115
- bool_to_int(b.ignored?),
116
- bool_to_int(b.suspended?),
117
118
  bool_to_int(b.thread.name.nil?),
118
119
  a.thread.object_id
119
120
  ] <=> [
120
121
  bool_to_int(current_thread?(b)),
121
- bool_to_int(a.ignored?),
122
- bool_to_int(a.suspended?),
123
122
  bool_to_int(a.thread.name.nil?),
124
123
  b.thread.object_id
125
124
  ]
@@ -139,9 +138,10 @@ module RubyJard
139
138
  end
140
139
 
141
140
  def thread_status_style(thread)
142
- if thread.status == 'run'
141
+ case thread.status
142
+ when 'run'
143
143
  :thread_status_run
144
- elsif thread.status == 'sleep'
144
+ when 'sleep'
145
145
  :thread_status_sleep
146
146
  else
147
147
  :thread_status_other
@@ -151,4 +151,4 @@ module RubyJard
151
151
  end
152
152
  end
153
153
 
154
- RubyJard::Screens.add_screen(:threads, RubyJard::Screens::ThreadsScreen)
154
+ RubyJard::Screens.add_screen('threads', RubyJard::Screens::ThreadsScreen)