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.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/ruby.yml +85 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +70 -1
- data/CHANGELOG.md +31 -0
- data/Gemfile +6 -3
- data/README.md +122 -8
- data/bin/console +1 -2
- data/docs/color_schemes/256-light.png +0 -0
- data/docs/color_schemes/gruvbox.png +0 -0
- data/docs/color_schemes/one-half-dark.png +0 -0
- data/docs/color_schemes/one-half-light.png +0 -0
- data/lib/ruby_jard.rb +5 -5
- data/lib/ruby_jard/box_drawer.rb +4 -1
- data/lib/ruby_jard/color_schemes.rb +31 -15
- data/lib/ruby_jard/color_schemes/256_color_scheme.rb +37 -37
- data/lib/ruby_jard/color_schemes/256_light_color_scheme.rb +62 -0
- data/lib/ruby_jard/color_schemes/deep_space_color_scheme.rb +36 -36
- data/lib/ruby_jard/color_schemes/gruvbox_color_scheme.rb +62 -0
- data/lib/ruby_jard/color_schemes/one_half_dark_color_scheme.rb +61 -0
- data/lib/ruby_jard/color_schemes/one_half_light_color_scheme.rb +62 -0
- data/lib/ruby_jard/column.rb +3 -1
- data/lib/ruby_jard/commands/continue_command.rb +2 -3
- data/lib/ruby_jard/commands/down_command.rb +9 -5
- data/lib/ruby_jard/commands/exit_command.rb +27 -0
- data/lib/ruby_jard/commands/frame_command.rb +11 -10
- data/lib/ruby_jard/commands/jard/color_scheme_command.rb +52 -0
- data/lib/ruby_jard/commands/jard/hide_command.rb +40 -0
- data/lib/ruby_jard/commands/jard/output_command.rb +28 -0
- data/lib/ruby_jard/commands/jard/show_command.rb +41 -0
- data/lib/ruby_jard/commands/jard_command.rb +50 -0
- data/lib/ruby_jard/commands/list_command.rb +5 -4
- data/lib/ruby_jard/commands/next_command.rb +10 -5
- data/lib/ruby_jard/commands/step_command.rb +10 -5
- data/lib/ruby_jard/commands/step_out_command.rb +10 -5
- data/lib/ruby_jard/commands/up_command.rb +10 -5
- data/lib/ruby_jard/commands/validation_helpers.rb +50 -0
- data/lib/ruby_jard/config.rb +7 -3
- data/lib/ruby_jard/console.rb +10 -22
- data/lib/ruby_jard/control_flow.rb +3 -3
- data/lib/ruby_jard/decorators/color_decorator.rb +11 -5
- data/lib/ruby_jard/decorators/loc_decorator.rb +1 -1
- data/lib/ruby_jard/decorators/path_decorator.rb +20 -7
- data/lib/ruby_jard/decorators/source_decorator.rb +2 -0
- data/lib/ruby_jard/frame.rb +55 -0
- data/lib/ruby_jard/keys.rb +0 -3
- data/lib/ruby_jard/layout.rb +9 -2
- data/lib/ruby_jard/layout_calculator.rb +29 -12
- data/lib/ruby_jard/layout_picker.rb +34 -0
- data/lib/ruby_jard/layouts.rb +52 -0
- data/lib/ruby_jard/layouts/narrow_horizontal_layout.rb +28 -0
- data/lib/ruby_jard/layouts/narrow_vertical_layout.rb +32 -0
- data/lib/ruby_jard/layouts/tiny_layout.rb +25 -0
- data/lib/ruby_jard/layouts/wide_layout.rb +13 -15
- data/lib/ruby_jard/pager.rb +96 -0
- data/lib/ruby_jard/repl_processor.rb +61 -31
- data/lib/ruby_jard/repl_proxy.rb +193 -89
- data/lib/ruby_jard/row.rb +16 -1
- data/lib/ruby_jard/row_renderer.rb +51 -42
- data/lib/ruby_jard/screen.rb +2 -12
- data/lib/ruby_jard/screen_adjuster.rb +104 -0
- data/lib/ruby_jard/screen_drawer.rb +3 -0
- data/lib/ruby_jard/screen_manager.rb +32 -54
- data/lib/ruby_jard/screen_renderer.rb +30 -16
- data/lib/ruby_jard/screens.rb +31 -12
- data/lib/ruby_jard/screens/backtrace_screen.rb +23 -26
- data/lib/ruby_jard/screens/menu_screen.rb +53 -22
- data/lib/ruby_jard/screens/source_screen.rb +65 -37
- data/lib/ruby_jard/screens/threads_screen.rb +14 -14
- data/lib/ruby_jard/screens/variables_screen.rb +59 -34
- data/lib/ruby_jard/session.rb +19 -10
- data/lib/ruby_jard/span.rb +3 -0
- data/lib/ruby_jard/templates/layout_template.rb +1 -1
- data/lib/ruby_jard/templates/screen_template.rb +3 -4
- data/lib/ruby_jard/version.rb +1 -1
- data/ruby_jard.gemspec +1 -1
- metadata +38 -9
- data/lib/ruby_jard/commands/color_scheme_command.rb +0 -42
- data/lib/ruby_jard/layouts/narrow_layout.rb +0 -41
- data/lib/ruby_jard/screens/empty_screen.rb +0 -13
data/lib/ruby_jard/repl_proxy.rb
CHANGED
@@ -1,14 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'ruby_jard/
|
5
|
-
require 'ruby_jard/commands/down_command'
|
6
|
-
require 'ruby_jard/commands/next_command'
|
7
|
-
require 'ruby_jard/commands/step_command'
|
8
|
-
require 'ruby_jard/commands/step_out_command'
|
9
|
-
require 'ruby_jard/commands/frame_command'
|
10
|
-
require 'ruby_jard/commands/list_command'
|
11
|
-
require 'ruby_jard/commands/color_scheme_command'
|
3
|
+
require 'pty'
|
4
|
+
require 'ruby_jard/pager'
|
12
5
|
|
13
6
|
module RubyJard
|
14
7
|
##
|
@@ -44,7 +37,6 @@ module RubyJard
|
|
44
37
|
'stat', # Included in jard UI
|
45
38
|
'backtrace', # Re-implemented later
|
46
39
|
'break', # Re-implemented later
|
47
|
-
'exit', # Conflicted with continue
|
48
40
|
'exit-all', # Conflicted with continue
|
49
41
|
'exit-program', # We already have `exit` native command
|
50
42
|
'!pry', # No need to complicate things
|
@@ -54,119 +46,218 @@ module RubyJard
|
|
54
46
|
'disable-pry' # No need to complicate things
|
55
47
|
].freeze
|
56
48
|
|
57
|
-
COMMANDS = [
|
58
|
-
CMD_FLOW = :flow,
|
59
|
-
CMD_EVALUATE = :evaluate,
|
60
|
-
CMD_IDLE = :idle,
|
61
|
-
CMD_INTERRUPT = :interrupt
|
62
|
-
].freeze
|
63
|
-
|
64
|
-
# rubocop:disable Layout/HashAlignment
|
65
49
|
INTERNAL_KEY_BINDINGS = {
|
66
|
-
RubyJard::Keys::
|
67
|
-
RubyJard::Keys::CTRL_C => (KEY_BINDING_INTERRUPT = :interrupt)
|
50
|
+
RubyJard::Keys::CTRL_C => (KEY_BINDING_INTERRUPT = :interrupt)
|
68
51
|
}.freeze
|
69
|
-
# rubocop:enable Layout/HashAlignment
|
70
52
|
|
71
|
-
|
53
|
+
KEY_READ_TIMEOUT = 0.2 # 200ms
|
54
|
+
PTY_OUTPUT_TIMEOUT = 1.to_f / 60 # 60hz
|
55
|
+
|
56
|
+
##
|
57
|
+
# A tool to communicate between functional threads and main threads
|
58
|
+
class FlowInterrupt < StandardError
|
59
|
+
attr_reader :flow
|
60
|
+
|
61
|
+
def initialize(msg = '', flow = nil)
|
62
|
+
super(msg)
|
63
|
+
@flow = flow
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# A class to store the state with multi-thread guarding
|
69
|
+
# Ready => Processing/Exiting
|
70
|
+
# Processing => Ready again
|
71
|
+
# Exiting => Exited
|
72
|
+
# Exited => Ready
|
73
|
+
class ReplState
|
74
|
+
STATES = [
|
75
|
+
STATE_READY = 0,
|
76
|
+
STATE_EXITING = 1,
|
77
|
+
STATE_PROCESSING = 2,
|
78
|
+
STATE_EXITED = 3
|
79
|
+
].freeze
|
80
|
+
def initialize
|
81
|
+
@state = STATE_EXITED
|
82
|
+
@mutex = Mutex.new
|
83
|
+
end
|
84
|
+
|
85
|
+
def check(method_name)
|
86
|
+
@mutex.synchronize { yield if send(method_name) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def ready?
|
90
|
+
@state == STATE_READY
|
91
|
+
end
|
92
|
+
|
93
|
+
def ready!
|
94
|
+
if ready? || processing? || exited?
|
95
|
+
@mutex.synchronize { @state = STATE_READY }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def processing?
|
100
|
+
@state == STATE_PROCESSING
|
101
|
+
end
|
102
|
+
|
103
|
+
def processing!
|
104
|
+
return unless ready?
|
105
|
+
|
106
|
+
@mutex.synchronize { @state = STATE_PROCESSING }
|
107
|
+
end
|
108
|
+
|
109
|
+
def exiting?
|
110
|
+
@state == STATE_EXITING
|
111
|
+
end
|
112
|
+
|
113
|
+
def exiting!
|
114
|
+
@mutex.synchronize { @state = STATE_EXITING }
|
115
|
+
end
|
116
|
+
|
117
|
+
def exited?
|
118
|
+
@state == STATE_EXITED
|
119
|
+
end
|
120
|
+
|
121
|
+
def exited!
|
122
|
+
@mutex.synchronize { @state = STATE_EXITED }
|
123
|
+
end
|
124
|
+
end
|
72
125
|
|
73
126
|
def initialize(key_bindings: nil)
|
74
|
-
@
|
127
|
+
@state = ReplState.new
|
128
|
+
|
129
|
+
@pry_input_pipe_read, @pry_input_pipe_write = IO.pipe
|
130
|
+
@pry_output_pty_read, @pry_output_pty_write = PTY.open
|
75
131
|
@pry = pry_instance
|
76
|
-
|
132
|
+
|
77
133
|
@key_bindings = key_bindings || RubyJard::KeyBindings.new
|
78
134
|
INTERNAL_KEY_BINDINGS.each do |sequence, action|
|
79
135
|
@key_bindings.push(sequence, action)
|
80
136
|
end
|
81
|
-
end
|
82
137
|
|
83
|
-
|
84
|
-
|
138
|
+
@pry_pty_output_thread = Thread.new { pry_pty_output }
|
139
|
+
@pry_pty_output_thread.name = '<<Jard: Pty Output Thread>>'
|
85
140
|
end
|
86
141
|
|
87
142
|
def repl(current_binding)
|
88
|
-
|
89
|
-
@
|
143
|
+
@state.ready!
|
144
|
+
@openning_pager = false
|
145
|
+
|
146
|
+
RubyJard::Console.disable_echo!
|
147
|
+
RubyJard::Console.raw!
|
148
|
+
|
149
|
+
Readline.input = @pry_input_pipe_read
|
150
|
+
Readline.output = @pry_output_pty_write
|
90
151
|
@pry.binding_stack.clear
|
91
152
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
153
|
+
@main_thread = Thread.current
|
154
|
+
|
155
|
+
@pry_input_thread = Thread.new { pry_repl(current_binding) }
|
156
|
+
@pry_input_thread.abort_on_exception = true
|
157
|
+
@pry_input_thread.report_on_exception = false
|
158
|
+
@pry_input_thread.name = '<<Jard: Pry input thread >>'
|
98
159
|
|
99
|
-
|
100
|
-
|
160
|
+
@key_listen_thread = Thread.new { listen_key_press }
|
161
|
+
@key_listen_thread.abort_on_exception = true
|
162
|
+
@key_listen_thread.report_on_exception = false
|
163
|
+
@key_listen_thread.name = '<<Jard: Repl key listen >>'
|
164
|
+
|
165
|
+
[@pry_input_thread, @key_listen_thread].map(&:join)
|
166
|
+
rescue FlowInterrupt => e
|
167
|
+
@state.exiting!
|
168
|
+
sleep PTY_OUTPUT_TIMEOUT until @state.exited?
|
169
|
+
RubyJard::ControlFlow.dispatch(e.flow)
|
170
|
+
ensure
|
171
|
+
RubyJard::Console.enable_echo!
|
172
|
+
RubyJard::Console.cooked!
|
173
|
+
Readline.input = STDIN
|
174
|
+
Readline.output = STDOUT
|
175
|
+
@key_listen_thread&.exit if @key_listen_thread&.alive?
|
176
|
+
@pry_input_thread&.exit if @pry_input_thread&.alive?
|
177
|
+
@state.exited!
|
178
|
+
end
|
179
|
+
|
180
|
+
private
|
181
|
+
|
182
|
+
def read_key
|
183
|
+
RubyJard::Console.getch(STDIN, KEY_READ_TIMEOUT)
|
184
|
+
end
|
185
|
+
|
186
|
+
def pry_pty_output
|
187
|
+
loop do
|
188
|
+
if @state.exiting?
|
189
|
+
if @pry_output_pty_read.ready?
|
190
|
+
STDOUT.write @pry_output_pty_read.read_nonblock(2048), from_jard: true
|
191
|
+
else
|
192
|
+
@state.exited!
|
193
|
+
end
|
194
|
+
elsif @state.exited?
|
195
|
+
sleep PTY_OUTPUT_TIMEOUT
|
101
196
|
else
|
102
|
-
|
103
|
-
|
197
|
+
output = @pry_output_pty_read.read_nonblock(2048)
|
198
|
+
unless output.nil?
|
199
|
+
STDOUT.write output, from_jard: true
|
200
|
+
end
|
104
201
|
end
|
202
|
+
rescue IO::WaitReadable, IO::WaitWritable
|
203
|
+
# Retry
|
204
|
+
sleep PTY_OUTPUT_TIMEOUT
|
105
205
|
end
|
106
|
-
pry_thread&.join
|
107
|
-
Readline.input = STDIN
|
108
206
|
end
|
109
207
|
|
110
208
|
def pry_repl(current_binding)
|
111
209
|
flow = RubyJard::ControlFlow.listen do
|
112
210
|
@pry.repl(current_binding)
|
113
211
|
end
|
114
|
-
@
|
115
|
-
|
116
|
-
|
117
|
-
raise
|
212
|
+
@state.check(:ready?) do
|
213
|
+
@main_thread.raise FlowInterrupt.new('Interrupt from repl thread', flow)
|
214
|
+
end
|
118
215
|
end
|
119
216
|
|
120
217
|
def listen_key_press
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
218
|
+
loop do
|
219
|
+
break if @state.exiting? || @state.exited?
|
220
|
+
|
221
|
+
if @state.processing? && @openning_pager
|
222
|
+
# Discard all keys unfortunately
|
223
|
+
sleep PTY_OUTPUT_TIMEOUT
|
224
|
+
else
|
225
|
+
key = @key_bindings.match { read_key }
|
226
|
+
if key.is_a?(RubyJard::KeyBinding)
|
227
|
+
continue = handle_key_binding(key)
|
228
|
+
break unless continue
|
229
|
+
elsif !key.empty?
|
230
|
+
@pry_input_pipe_write.write(key)
|
231
|
+
end
|
232
|
+
end
|
126
233
|
end
|
127
234
|
end
|
128
235
|
|
129
236
|
def handle_key_binding(key_binding)
|
130
237
|
case key_binding.action
|
131
|
-
when KEY_BINDING_ENDLINE
|
132
|
-
@pry_write_stream.write(key_binding.sequence)
|
133
|
-
@commands << [CMD_EVALUATE]
|
134
238
|
when KEY_BINDING_INTERRUPT
|
135
|
-
|
239
|
+
handle_interrupt_command
|
240
|
+
true
|
136
241
|
else
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def handle_command(pry_thread, cmd, value)
|
144
|
-
case cmd
|
145
|
-
when CMD_FLOW
|
146
|
-
pry_thread.exit if pry_thread.alive?
|
147
|
-
RubyJard::ControlFlow.dispatch(value)
|
148
|
-
when CMD_EVALUATE
|
149
|
-
loop do
|
150
|
-
cmd, value = @commands.deq
|
151
|
-
break if [CMD_IDLE, CMD_FLOW, CMD_INTERRUPT].include?(cmd)
|
242
|
+
flow = RubyJard::ControlFlow.new(:key_binding, action: key_binding.action)
|
243
|
+
@state.check(:ready?) do
|
244
|
+
@main_thread.raise FlowInterrupt.new('Interrupt from repl thread', flow)
|
152
245
|
end
|
153
|
-
|
154
|
-
when CMD_INTERRUPT
|
155
|
-
handle_interrupt_command(pry_thread)
|
156
|
-
when CMD_IDLE
|
157
|
-
# Ignore
|
246
|
+
false
|
158
247
|
end
|
159
248
|
end
|
160
249
|
|
161
|
-
def handle_interrupt_command
|
162
|
-
|
250
|
+
def handle_interrupt_command
|
251
|
+
@state.check(:ready?) do
|
252
|
+
@pry_input_thread&.raise Interrupt if @pry_input_thread&.alive?
|
253
|
+
end
|
163
254
|
loop do
|
164
255
|
begin
|
165
|
-
sleep
|
256
|
+
sleep PTY_OUTPUT_TIMEOUT
|
166
257
|
rescue Interrupt
|
167
258
|
# Interrupt spam. Ignore.
|
168
259
|
end
|
169
|
-
break unless
|
260
|
+
break unless @pry_input_thread&.pending_interrupt?
|
170
261
|
end
|
171
262
|
end
|
172
263
|
|
@@ -175,7 +266,8 @@ module RubyJard
|
|
175
266
|
prompt: pry_jard_prompt,
|
176
267
|
quiet: true,
|
177
268
|
commands: pry_command_set,
|
178
|
-
hooks: pry_hooks
|
269
|
+
hooks: pry_hooks,
|
270
|
+
output: @pry_output_pty_write
|
179
271
|
)
|
180
272
|
# I'll be burned in hell for this
|
181
273
|
# TODO: Contact pry author to add :after_handle_line hook
|
@@ -186,6 +278,10 @@ module RubyJard
|
|
186
278
|
end
|
187
279
|
alias_method :_original_handle_line, :handle_line
|
188
280
|
alias_method :handle_line, :_jard_handle_line
|
281
|
+
|
282
|
+
def pager
|
283
|
+
RubyJard::Pager.new(self)
|
284
|
+
end
|
189
285
|
end
|
190
286
|
pry_instance
|
191
287
|
end
|
@@ -215,18 +311,26 @@ module RubyJard
|
|
215
311
|
|
216
312
|
def pry_hooks
|
217
313
|
hooks = Pry::Hooks.default
|
218
|
-
hooks.add_hook(:after_read, :jard_proxy_acquire_lock) do |
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
[CMD_IDLE]
|
224
|
-
end
|
225
|
-
rescue SyntaxError
|
226
|
-
@commands << [CMD_IDLE]
|
314
|
+
hooks.add_hook(:after_read, :jard_proxy_acquire_lock) do |_read_string, _pry|
|
315
|
+
RubyJard::Console.cooked!
|
316
|
+
@state.processing!
|
317
|
+
# Sleep 2 ticks, wait for pry to print out all existing output in the queue
|
318
|
+
sleep PTY_OUTPUT_TIMEOUT * 2
|
227
319
|
end
|
228
320
|
hooks.add_hook(:after_handle_line, :jard_proxy_release_lock) do
|
229
|
-
|
321
|
+
RubyJard::Console.raw!
|
322
|
+
@state.ready!
|
323
|
+
end
|
324
|
+
hooks.add_hook(:before_pager, :jard_proxy_before_pager) do
|
325
|
+
@openning_pager = true
|
326
|
+
|
327
|
+
@state.processing!
|
328
|
+
RubyJard::Console.cooked!
|
329
|
+
end
|
330
|
+
hooks.add_hook(:after_pager, :jard_proxy_after_pager) do
|
331
|
+
@openning_pager = false
|
332
|
+
@state.ready!
|
333
|
+
RubyJard::Console.raw!
|
230
334
|
end
|
231
335
|
end
|
232
336
|
end
|
data/lib/ruby_jard/row.rb
CHANGED
@@ -1,16 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module RubyJard
|
4
|
+
##
|
5
|
+
# This class is an object to store a row of data display on a screen
|
4
6
|
class Row
|
5
7
|
extend Forwardable
|
6
8
|
|
7
|
-
attr_accessor :columns, :line_limit, :content
|
9
|
+
attr_accessor :columns, :line_limit, :content, :rendered
|
8
10
|
|
9
11
|
def initialize(line_limit: 1, columns: [], ellipsis: true)
|
10
12
|
@content = []
|
11
13
|
@columns = columns
|
12
14
|
@ellipsis = ellipsis
|
13
15
|
@line_limit = line_limit
|
16
|
+
@rendered = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def rendered?
|
20
|
+
@rendered == true
|
21
|
+
end
|
22
|
+
|
23
|
+
def mark_rendered
|
24
|
+
@rendered = true
|
25
|
+
end
|
26
|
+
|
27
|
+
def reset_rendered
|
28
|
+
@rendered = false
|
14
29
|
end
|
15
30
|
end
|
16
31
|
end
|
@@ -14,63 +14,72 @@ module RubyJard
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def render
|
17
|
+
@row.reset_rendered
|
18
|
+
|
17
19
|
@x = 0
|
18
20
|
@y = 0
|
21
|
+
@original_x = 0
|
22
|
+
@original_y = 0
|
19
23
|
@content_map = []
|
20
24
|
|
21
|
-
|
22
|
-
|
23
|
-
@y =
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
render_column(column, original_x, content_width)
|
25
|
+
@row.columns.each do |column|
|
26
|
+
@x = @original_x
|
27
|
+
@y = @original_y
|
28
|
+
|
29
|
+
@drawing_width = 0
|
30
|
+
@drawing_lines = 1
|
28
31
|
|
29
|
-
|
32
|
+
column.spans.each do |span|
|
33
|
+
render_span(column, span)
|
34
|
+
end
|
35
|
+
|
36
|
+
@original_x += column.width
|
30
37
|
end
|
31
38
|
|
32
39
|
generate_bitmap
|
40
|
+
|
41
|
+
@row.mark_rendered
|
33
42
|
end
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
lines += 1
|
47
|
-
@y += 1
|
48
|
-
@x = original_x
|
49
|
-
end
|
50
|
-
elsif column.word_wrap == RubyJard::Column::WORD_WRAP_BREAK_WORD
|
51
|
-
if content_width - width <= 0
|
52
|
-
width = 0
|
53
|
-
lines += 1
|
54
|
-
@y += 1
|
55
|
-
@x = original_x
|
56
|
-
end
|
57
|
-
elsif content_width - width <= 0
|
58
|
-
return
|
44
|
+
# rubocop:disable Metrics/MethodLength
|
45
|
+
def render_span(column, span)
|
46
|
+
line_content = span.content
|
47
|
+
|
48
|
+
until line_content.nil? || line_content.empty?
|
49
|
+
if column.word_wrap == RubyJard::Column::WORD_WRAP_NORMAL
|
50
|
+
if column.content_width - @drawing_width < line_content.length && @drawing_width != 0
|
51
|
+
@drawing_width = 0
|
52
|
+
@drawing_lines += 1
|
53
|
+
@y += 1
|
54
|
+
@x = @original_x
|
59
55
|
end
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
draw_content(drawing_content, span.styles)
|
67
|
-
return
|
68
|
-
else
|
69
|
-
draw_content(drawing_content, span.styles)
|
56
|
+
elsif column.word_wrap == RubyJard::Column::WORD_WRAP_BREAK_WORD
|
57
|
+
if column.content_width - @drawing_width <= 0
|
58
|
+
@drawing_width = 0
|
59
|
+
@drawing_lines += 1
|
60
|
+
@y += 1
|
61
|
+
@x = @original_x
|
70
62
|
end
|
63
|
+
elsif column.content_width - @drawing_width <= 0
|
64
|
+
return
|
65
|
+
end
|
66
|
+
drawing_content = line_content[0..column.content_width - @drawing_width - 1]
|
67
|
+
line_content = line_content[column.content_width - @drawing_width..-1]
|
68
|
+
@drawing_width += drawing_content.length
|
69
|
+
|
70
|
+
if !@row.line_limit.nil? &&
|
71
|
+
@drawing_lines >= @row.line_limit &&
|
72
|
+
!line_content.nil? &&
|
73
|
+
!line_content.empty?
|
74
|
+
drawing_content[drawing_content.length - ELLIPSIS.length..-1] = ELLIPSIS
|
75
|
+
draw_content(drawing_content, span.styles)
|
76
|
+
return
|
77
|
+
else
|
78
|
+
draw_content(drawing_content, span.styles)
|
71
79
|
end
|
72
80
|
end
|
73
81
|
end
|
82
|
+
# rubocop:enable Metrics/MethodLength
|
74
83
|
|
75
84
|
def draw_content(drawing_content, styles)
|
76
85
|
return if @y < 0 || @y >= @height
|