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,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)