ruby_jard 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +0 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +21 -0
- data/README.md +16 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/lib/ruby_jard.rb +77 -0
- data/lib/ruby_jard/commands/continue_command.rb +33 -0
- data/lib/ruby_jard/commands/down_command.rb +31 -0
- data/lib/ruby_jard/commands/finish_command.rb +31 -0
- data/lib/ruby_jard/commands/frame_command.rb +36 -0
- data/lib/ruby_jard/commands/next_command.rb +31 -0
- data/lib/ruby_jard/commands/step_command.rb +31 -0
- data/lib/ruby_jard/commands/up_command.rb +31 -0
- data/lib/ruby_jard/decorators/loc_decorator.rb +200 -0
- data/lib/ruby_jard/decorators/path_decorator.rb +88 -0
- data/lib/ruby_jard/decorators/source_decorator.rb +43 -0
- data/lib/ruby_jard/decorators/text_decorator.rb +61 -0
- data/lib/ruby_jard/layout.rb +99 -0
- data/lib/ruby_jard/layout_template.rb +101 -0
- data/lib/ruby_jard/repl_processor.rb +143 -0
- data/lib/ruby_jard/screen.rb +61 -0
- data/lib/ruby_jard/screen_manager.rb +121 -0
- data/lib/ruby_jard/screens.rb +26 -0
- data/lib/ruby_jard/screens/backtrace_screen.rb +150 -0
- data/lib/ruby_jard/screens/breakpoints_screen.rb +23 -0
- data/lib/ruby_jard/screens/empty_screen.rb +13 -0
- data/lib/ruby_jard/screens/expressions_sreen.rb +22 -0
- data/lib/ruby_jard/screens/menu_screen.rb +62 -0
- data/lib/ruby_jard/screens/source_screen.rb +133 -0
- data/lib/ruby_jard/screens/threads_screen.rb +116 -0
- data/lib/ruby_jard/screens/variables_screen.rb +234 -0
- data/lib/ruby_jard/session.rb +54 -0
- data/lib/ruby_jard/version.rb +6 -0
- data/ruby_jard.gemspec +39 -0
- metadata +160 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
##
|
5
|
+
# Screen registry. The screens call add_screen right after they are declared.
|
6
|
+
module Screens
|
7
|
+
class << self
|
8
|
+
def screen_registry
|
9
|
+
@screen_registry ||= {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_screen(name, screen_class)
|
13
|
+
unless screen_class < RubyJard::Screen
|
14
|
+
raise RubyJard::Error, "#{screen_class} must implement, and inherit from #{RubyJard::Screen}"
|
15
|
+
end
|
16
|
+
|
17
|
+
screen_registry[name] = screen_class
|
18
|
+
end
|
19
|
+
|
20
|
+
def [](name)
|
21
|
+
screen_registry[name]
|
22
|
+
end
|
23
|
+
alias get []
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
module Screens
|
5
|
+
class BacktraceScreen < RubyJard::Screen
|
6
|
+
def draw
|
7
|
+
@output.print TTY::Box.frame(**frame_styles)
|
8
|
+
|
9
|
+
@output.print TTY::Cursor.move_to(@col + 2, @row)
|
10
|
+
@output.print decorate_text
|
11
|
+
.with_highlight(true)
|
12
|
+
.text(" Backtrace (#{frames_count}) ", :bright_yellow)
|
13
|
+
.content
|
14
|
+
|
15
|
+
decorate_frames.each_with_index do |frame_texts, index|
|
16
|
+
left, right = frame_texts
|
17
|
+
@output.print TTY::Cursor.move_to(@col + 1, @row + index + 1)
|
18
|
+
@output.print left.content
|
19
|
+
|
20
|
+
next unless @col + left.length < @col + @layout.width - right.length - 1
|
21
|
+
|
22
|
+
# TODO: handle reducable components in case of smaller screen
|
23
|
+
@output.print TTY::Cursor.move_to(@col + @layout.width - right.length, @row + index + 1)
|
24
|
+
@output.print right.content
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def data_size
|
31
|
+
@layout.height - 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def frame_styles
|
35
|
+
default_frame_styles.merge(
|
36
|
+
top: @row, left: @col, width: @layout.width, height: @layout.height
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def decorate_frames
|
41
|
+
return [] if data_size.zero?
|
42
|
+
|
43
|
+
window_start = frame_pos / data_size * data_size
|
44
|
+
window_end = [frames_count, window_start + data_size - 1].min
|
45
|
+
|
46
|
+
backtrace[window_start..window_end]
|
47
|
+
.map
|
48
|
+
.with_index do |frame, frame_index|
|
49
|
+
decorate_frame(frame, window_start + frame_index, window_start, window_end)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def decorate_frame(line, frame_id, window_start, window_end)
|
54
|
+
location = line[0]
|
55
|
+
object = line[1]
|
56
|
+
klass = line[2]
|
57
|
+
|
58
|
+
left =
|
59
|
+
decorate_frame_id(frame_id, window_start, window_end) +
|
60
|
+
' ' +
|
61
|
+
decorate_location_label(frame_id, location, object, klass)
|
62
|
+
right = decorate_location_path(frame_id, location)
|
63
|
+
|
64
|
+
[left, right]
|
65
|
+
end
|
66
|
+
|
67
|
+
def reset
|
68
|
+
@color = Pastel.new
|
69
|
+
end
|
70
|
+
|
71
|
+
def decorate_frame_id(frame_id, _window_start, window_end)
|
72
|
+
decorate_text
|
73
|
+
.with_highlight(frame_pos == frame_id)
|
74
|
+
.text(frame_pos == frame_id ? '→ ' : ' ', :white)
|
75
|
+
.text(frame_id.to_s.ljust(window_end.to_s.length), frame_pos == frame_id ? :bright_yellow : :white)
|
76
|
+
end
|
77
|
+
|
78
|
+
def decorate_location_label(frame_id, location, object, klass)
|
79
|
+
decorate_text
|
80
|
+
.with_highlight(frame_pos == frame_id)
|
81
|
+
.text(backtrace[frame_id].last.nil? ? '[c] ' : '', :green)
|
82
|
+
.text(decorate_object_label(object, klass), :green)
|
83
|
+
.text(' in ', :white)
|
84
|
+
.text(decorate_method_label(location), :green)
|
85
|
+
end
|
86
|
+
|
87
|
+
def decorate_object_label(object, klass)
|
88
|
+
if klass.nil? || object.class == klass
|
89
|
+
if object.is_a?(Class)
|
90
|
+
object.name
|
91
|
+
else
|
92
|
+
object.class.name
|
93
|
+
end
|
94
|
+
elsif klass.singleton_class?
|
95
|
+
# No easy way to get the original class of a singleton class
|
96
|
+
object.name
|
97
|
+
else
|
98
|
+
klass.name
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def decorate_method_label(location)
|
103
|
+
if location.label != location.base_label
|
104
|
+
"#{location.base_label} (#{location.label.split(' ').first})"
|
105
|
+
else
|
106
|
+
location.base_label
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def decorate_location_path(frame_id, location)
|
111
|
+
decorated_path = decorate_path(location.absolute_path, location.lineno)
|
112
|
+
|
113
|
+
if decorated_path.gem?
|
114
|
+
decorate_text
|
115
|
+
.with_highlight(frame_pos == frame_id)
|
116
|
+
.text('in ', :bright_white)
|
117
|
+
.text(decorated_path.gem, :bright_white)
|
118
|
+
.text(' (', :bright_white)
|
119
|
+
.text(decorated_path.gem_version, :bright_white)
|
120
|
+
.text(')', :bright_white)
|
121
|
+
else
|
122
|
+
decorate_text
|
123
|
+
.with_highlight(frame_pos == frame_id)
|
124
|
+
.text('at ', :bright_white)
|
125
|
+
.text(decorated_path.path, :bright_white)
|
126
|
+
.text(':', :bright_white)
|
127
|
+
.text(decorated_path.lineno, :bright_white)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def frame_pos
|
132
|
+
if @session.frame.nil?
|
133
|
+
0
|
134
|
+
else
|
135
|
+
@session.frame.pos.to_i
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def frames_count
|
140
|
+
@session.backtrace.length
|
141
|
+
end
|
142
|
+
|
143
|
+
def backtrace
|
144
|
+
@session.backtrace
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
RubyJard::Screens.add_screen(:backtrace, RubyJard::Screens::BacktraceScreen)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
module Screens
|
5
|
+
class BreakpointsScreen < RubyJard::Screen
|
6
|
+
def draw
|
7
|
+
@output.print TTY::Box.frame(
|
8
|
+
**default_frame_styles.merge(
|
9
|
+
top: @row, left: @col, width: @layout.width, height: @layout.height
|
10
|
+
)
|
11
|
+
)
|
12
|
+
|
13
|
+
@output.print TTY::Cursor.move_to(@col + 2, @row)
|
14
|
+
@output.print decorate_text
|
15
|
+
.with_highlight(true)
|
16
|
+
.text(' Breakpoints ', :bright_yellow)
|
17
|
+
.content
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
RubyJard::Screens.add_screen(:breakpoints, RubyJard::Screens::BreakpointsScreen)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
module Screens
|
5
|
+
class ExpressionsScreen < RubyJard::Screen
|
6
|
+
def draw
|
7
|
+
@output.print TTY::Box.frame(
|
8
|
+
**default_frame_styles.merge(
|
9
|
+
top: @row, left: @col, width: @layout.width, height: @layout.height
|
10
|
+
)
|
11
|
+
)
|
12
|
+
@output.print TTY::Cursor.move_to(@col + 2, @row)
|
13
|
+
@output.print decorate_text
|
14
|
+
.with_highlight(true)
|
15
|
+
.text(' Expressions ', :bright_yellow)
|
16
|
+
.content
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
RubyJard::Screens.add_screen(:expressions, RubyJard::Screens::ExpressionsScreen)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
module Screens
|
5
|
+
class MenuScreen < RubyJard::Screen
|
6
|
+
def draw
|
7
|
+
@output.print TTY::Cursor.move_to(@col, @row)
|
8
|
+
frame = TTY::Box.frame(
|
9
|
+
**default_frame_styles.merge(
|
10
|
+
top: @row, left: @col, width: @layout.width, height: @layout.height,
|
11
|
+
border: {
|
12
|
+
left: false,
|
13
|
+
top: :line,
|
14
|
+
right: false,
|
15
|
+
bottom: false
|
16
|
+
},
|
17
|
+
style: {
|
18
|
+
fg: :white
|
19
|
+
}
|
20
|
+
)
|
21
|
+
)
|
22
|
+
@output.print frame
|
23
|
+
|
24
|
+
margin = 0
|
25
|
+
left_menu = generate_left_menu
|
26
|
+
left_menu.each do |item|
|
27
|
+
@output.print TTY::Cursor.move_to(@col + 1 + margin, @row + 1)
|
28
|
+
@output.print item.content
|
29
|
+
margin += item.length + 3
|
30
|
+
end
|
31
|
+
|
32
|
+
margin = 0
|
33
|
+
right_menu = generate_right_menu
|
34
|
+
right_menu.reverse.each do |item|
|
35
|
+
@output.print TTY::Cursor.move_to(@col + @layout.width - margin - item.length - 1, @row + 1)
|
36
|
+
@output.print item.content
|
37
|
+
margin += item.length + 3
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def generate_left_menu
|
44
|
+
[
|
45
|
+
decorate_text.with_highlight(true).text('Debug console (F5)', :bright_yellow),
|
46
|
+
decorate_text.text('Program output (F6)', :white)
|
47
|
+
]
|
48
|
+
end
|
49
|
+
|
50
|
+
def generate_right_menu
|
51
|
+
[
|
52
|
+
decorate_text.text('Step (F7)', :white),
|
53
|
+
decorate_text.text('Next (F8)', :white),
|
54
|
+
decorate_text.text('Step out (Shift+F8)', :white),
|
55
|
+
decorate_text.text('Continue (F9)', :white)
|
56
|
+
]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
RubyJard::Screens.add_screen(:menu, RubyJard::Screens::MenuScreen)
|
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
module Screens
|
5
|
+
class SourceScreen < RubyJard::Screen
|
6
|
+
def draw
|
7
|
+
@output.print TTY::Box.frame(
|
8
|
+
**default_frame_styles.merge(
|
9
|
+
top: @row, left: @col, width: @layout.width, height: @layout.height
|
10
|
+
)
|
11
|
+
)
|
12
|
+
|
13
|
+
@output.print TTY::Cursor.move_to(@col + 2, @row)
|
14
|
+
@output.print decorate_text
|
15
|
+
.with_highlight(true)
|
16
|
+
.text(' Source', :bright_yellow)
|
17
|
+
.text(' (', :bright_yellow)
|
18
|
+
.text(file_path, :bright_yellow)
|
19
|
+
.text(') ', :bright_yellow)
|
20
|
+
.content
|
21
|
+
|
22
|
+
decorate_codes.each_with_index do |decorated_loc, index|
|
23
|
+
@output.print TTY::Cursor.move_to(@col + 1, @row + 1 + index)
|
24
|
+
@output.print decorated_loc.content
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def data_size
|
31
|
+
@layout.height - 1
|
32
|
+
end
|
33
|
+
|
34
|
+
def decorate_codes
|
35
|
+
return [] if RubyJard.current_session.frame.nil?
|
36
|
+
|
37
|
+
decorated_source = decorate_source(current_file, current_line, data_size)
|
38
|
+
|
39
|
+
lineno_padding = decorated_source.window_end.to_s.length
|
40
|
+
|
41
|
+
decorated_source.codes.map.with_index do |loc, index|
|
42
|
+
lineno = decorated_source.window_start + index
|
43
|
+
decorated_loc = decorate_loc(loc, current_line == lineno)
|
44
|
+
|
45
|
+
if current_line == lineno
|
46
|
+
decorate_text
|
47
|
+
.with_highlight(true)
|
48
|
+
.text('→ ')
|
49
|
+
.text(lineno.to_s.ljust(lineno_padding), :bright_yellow)
|
50
|
+
.text(' ')
|
51
|
+
.text(decorated_loc.loc)
|
52
|
+
.text(inline_variables(decorated_loc.tokens))
|
53
|
+
else
|
54
|
+
decorate_text
|
55
|
+
.with_highlight(false)
|
56
|
+
.text(' ')
|
57
|
+
.text(lineno.to_s.ljust(lineno_padding), :white)
|
58
|
+
.text(' ')
|
59
|
+
.text(decorated_loc.loc)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def file_path
|
65
|
+
return '' if RubyJard.current_session.frame.nil?
|
66
|
+
|
67
|
+
decorated_path = decorate_path(current_file, current_line)
|
68
|
+
if decorated_path.gem?
|
69
|
+
"#{decorated_path.gem}: #{decorated_path.path}:#{decorated_path.lineno}"
|
70
|
+
else
|
71
|
+
"#{decorated_path.path}:#{decorated_path.lineno}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def current_binding
|
76
|
+
RubyJard.current_session.frame._binding
|
77
|
+
end
|
78
|
+
|
79
|
+
def current_frame_scope
|
80
|
+
RubyJard.current_session.backtrace[RubyJard.current_session.frame.pos][1]
|
81
|
+
end
|
82
|
+
|
83
|
+
def current_file
|
84
|
+
RubyJard.current_session.frame.file
|
85
|
+
end
|
86
|
+
|
87
|
+
def current_line
|
88
|
+
RubyJard.current_session.frame.line
|
89
|
+
end
|
90
|
+
|
91
|
+
def inline_variables(tokens)
|
92
|
+
variables = {}
|
93
|
+
local_variables = current_binding.local_variables
|
94
|
+
instance_variables = current_frame_scope.instance_variables
|
95
|
+
|
96
|
+
tokens.each_slice(2).each do |token, kind|
|
97
|
+
token = token.to_sym
|
98
|
+
|
99
|
+
if kind == :ident && local_variables.include?(token)
|
100
|
+
var = current_binding.local_variable_get(token)
|
101
|
+
elsif kind == :instance_variable && instance_variables.include?(token)
|
102
|
+
var = current_frame_scope.instance_variable_get(token)
|
103
|
+
else
|
104
|
+
next
|
105
|
+
end
|
106
|
+
|
107
|
+
next if variables.key?(token)
|
108
|
+
|
109
|
+
var_inspect = var.inspect
|
110
|
+
# TODO: dynamic fill the rest of the line instead
|
111
|
+
variables[token] = var_inspect if var_inspect.length < 30
|
112
|
+
end
|
113
|
+
|
114
|
+
return '' if variables.empty?
|
115
|
+
|
116
|
+
variables_text = decorate_text.with_highlight(false).text(' #→ ', :white)
|
117
|
+
variables.to_a.each_with_index do |(var_name, var_inspect), index|
|
118
|
+
variables_text
|
119
|
+
.with_highlight(false)
|
120
|
+
.text(var_name.to_s, :white)
|
121
|
+
.text('=', :white)
|
122
|
+
.text(var_inspect, :white)
|
123
|
+
|
124
|
+
variables_text.with_highlight(false).text(', ', :white) if index != variables.length - 1
|
125
|
+
end
|
126
|
+
|
127
|
+
variables_text
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
RubyJard::Screens.add_screen(:source, RubyJard::Screens::SourceScreen)
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyJard
|
4
|
+
module Screens
|
5
|
+
class ThreadsScreen < RubyJard::Screen
|
6
|
+
def draw
|
7
|
+
@output.print TTY::Box.frame(
|
8
|
+
**default_frame_styles.merge(
|
9
|
+
top: @row, left: @col, width: @layout.width, height: @layout.height
|
10
|
+
)
|
11
|
+
)
|
12
|
+
|
13
|
+
decorated_threads = decorate_threads
|
14
|
+
|
15
|
+
@output.print TTY::Cursor.move_to(@col + 1, @row)
|
16
|
+
@output.print decorate_text
|
17
|
+
.with_highlight(true)
|
18
|
+
.text(" Threads (#{RubyJard.current_session.contexts.length}) ", :bright_yellow)
|
19
|
+
.content
|
20
|
+
|
21
|
+
decorated_threads.each_with_index do |thread, index|
|
22
|
+
@output.print TTY::Cursor.move_to(@col + 1, @row + index + 1)
|
23
|
+
@output.print thread.content
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def data_size
|
30
|
+
@layout.height - 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def decorate_threads
|
34
|
+
contexts = sort_contexts(RubyJard.current_session.contexts)
|
35
|
+
num_padding = contexts.length.to_s.length
|
36
|
+
contexts.first(data_size).map do |context|
|
37
|
+
decorate_text
|
38
|
+
.with_highlight(current_thread?(context))
|
39
|
+
.text(current_thread?(context) ? '→ ' : ' ', :bright_white)
|
40
|
+
.text(context_color(context, "T#{context.thread.object_id}"))
|
41
|
+
.with_highlight(false)
|
42
|
+
.text(" (#{context.thread.status}) ", :white)
|
43
|
+
.with_highlight(current_thread?(context))
|
44
|
+
.text(thread_name(context), :bright_white)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def sort_contexts(contexts)
|
49
|
+
# Sort: current context first
|
50
|
+
# Sort: not debug context first
|
51
|
+
# Sort: not suspended context first
|
52
|
+
# Sort: sort by thread num
|
53
|
+
contexts.sort do |a, b|
|
54
|
+
[
|
55
|
+
bool_to_int(current_thread?(a)),
|
56
|
+
bool_to_int(b.ignored?),
|
57
|
+
bool_to_int(b.suspended?),
|
58
|
+
bool_to_int(b.thread.name.nil?),
|
59
|
+
a.thread.object_id
|
60
|
+
] <=> [
|
61
|
+
bool_to_int(current_thread?(b)),
|
62
|
+
bool_to_int(a.ignored?),
|
63
|
+
bool_to_int(a.suspended?),
|
64
|
+
bool_to_int(a.thread.name.nil?),
|
65
|
+
b.thread.object_id
|
66
|
+
]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def bool_to_int(bool)
|
71
|
+
bool == true ? -1 : 1
|
72
|
+
end
|
73
|
+
|
74
|
+
def current_thread?(context)
|
75
|
+
context.thread == Thread.current
|
76
|
+
end
|
77
|
+
|
78
|
+
def context_color(context, text)
|
79
|
+
if current_thread?(context)
|
80
|
+
decorate_text
|
81
|
+
.with_highlight(true)
|
82
|
+
.text(text, :bright_yellow)
|
83
|
+
elsif context.suspended?
|
84
|
+
decorate_text
|
85
|
+
.with_highlight(false)
|
86
|
+
.text(text, :red)
|
87
|
+
elsif context.ignored?
|
88
|
+
decorate_text
|
89
|
+
.with_highlight(false)
|
90
|
+
.text(text, :white)
|
91
|
+
else
|
92
|
+
decorate_text
|
93
|
+
.with_highlight(false)
|
94
|
+
.text(text, :bright_white)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def thread_name(context)
|
99
|
+
if context.thread.name.nil?
|
100
|
+
last_backtrace =
|
101
|
+
if context == RubyJard.current_session.current_context
|
102
|
+
context.backtrace[0][0]
|
103
|
+
else
|
104
|
+
context.thread.backtrace_locations[0]
|
105
|
+
end
|
106
|
+
location = decorate_path(last_backtrace.path, last_backtrace.lineno)
|
107
|
+
"#{location.path}:#{location.lineno}"
|
108
|
+
else
|
109
|
+
context.thread.name
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
RubyJard::Screens.add_screen(:threads, RubyJard::Screens::ThreadsScreen)
|