reline 0.5.2 → 0.5.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -43,11 +43,13 @@ class Reline::Unicode
43
43
 
44
44
  def self.escape_for_print(str)
45
45
  str.chars.map! { |gr|
46
- escaped = EscapedPairs[gr.ord]
47
- if escaped && gr != -"\n" && gr != -"\t"
48
- escaped
49
- else
46
+ case gr
47
+ when -"\n"
50
48
  gr
49
+ when -"\t"
50
+ -' '
51
+ else
52
+ EscapedPairs[gr.ord] || gr
51
53
  end
52
54
  }.join
53
55
  end
@@ -128,10 +130,10 @@ class Reline::Unicode
128
130
  end
129
131
  end
130
132
 
131
- def self.split_by_width(str, max_width, encoding = str.encoding)
133
+ def self.split_by_width(str, max_width, encoding = str.encoding, offset: 0)
132
134
  lines = [String.new(encoding: encoding)]
133
135
  height = 1
134
- width = 0
136
+ width = offset
135
137
  rest = str.encode(Encoding::UTF_8)
136
138
  in_zero_width = false
137
139
  seq = String.new(encoding: encoding)
@@ -145,7 +147,13 @@ class Reline::Unicode
145
147
  lines.last << NON_PRINTING_END
146
148
  when csi
147
149
  lines.last << csi
148
- seq << csi
150
+ unless in_zero_width
151
+ if csi == -"\e[m" || csi == -"\e[0m"
152
+ seq.clear
153
+ else
154
+ seq << csi
155
+ end
156
+ end
149
157
  when osc
150
158
  lines.last << osc
151
159
  seq << osc
@@ -173,32 +181,78 @@ class Reline::Unicode
173
181
 
174
182
  # Take a chunk of a String cut by width with escape sequences.
175
183
  def self.take_range(str, start_col, max_width)
184
+ take_mbchar_range(str, start_col, max_width).first
185
+ end
186
+
187
+ def self.take_mbchar_range(str, start_col, width, cover_begin: false, cover_end: false, padding: false)
176
188
  chunk = String.new(encoding: str.encoding)
189
+
190
+ end_col = start_col + width
177
191
  total_width = 0
178
192
  rest = str.encode(Encoding::UTF_8)
179
193
  in_zero_width = false
194
+ chunk_start_col = nil
195
+ chunk_end_col = nil
196
+ has_csi = false
180
197
  rest.scan(WIDTH_SCANNER) do |non_printing_start, non_printing_end, csi, osc, gc|
181
198
  case
182
199
  when non_printing_start
183
200
  in_zero_width = true
201
+ chunk << NON_PRINTING_START
184
202
  when non_printing_end
185
203
  in_zero_width = false
204
+ chunk << NON_PRINTING_END
186
205
  when csi
206
+ has_csi = true
187
207
  chunk << csi
188
208
  when osc
189
209
  chunk << osc
190
210
  when gc
191
211
  if in_zero_width
192
212
  chunk << gc
213
+ next
214
+ end
215
+
216
+ mbchar_width = get_mbchar_width(gc)
217
+ prev_width = total_width
218
+ total_width += mbchar_width
219
+
220
+ if (cover_begin || padding ? total_width <= start_col : prev_width < start_col)
221
+ # Current character haven't reached start_col yet
222
+ next
223
+ elsif padding && !cover_begin && prev_width < start_col && start_col < total_width
224
+ # Add preceding padding. This padding might have background color.
225
+ chunk << ' '
226
+ chunk_start_col ||= start_col
227
+ chunk_end_col = total_width
228
+ next
229
+ elsif (cover_end ? prev_width < end_col : total_width <= end_col)
230
+ # Current character is in the range
231
+ chunk << gc
232
+ chunk_start_col ||= prev_width
233
+ chunk_end_col = total_width
234
+ break if total_width >= end_col
193
235
  else
194
- mbchar_width = get_mbchar_width(gc)
195
- total_width += mbchar_width
196
- break if (start_col + max_width) < total_width
197
- chunk << gc if start_col < total_width
236
+ # Current character exceeds end_col
237
+ if padding && end_col < total_width
238
+ # Add succeeding padding. This padding might have background color.
239
+ chunk << ' '
240
+ chunk_start_col ||= prev_width
241
+ chunk_end_col = end_col
242
+ end
243
+ break
198
244
  end
199
245
  end
200
246
  end
201
- chunk
247
+ chunk_start_col ||= start_col
248
+ chunk_end_col ||= start_col
249
+ if padding && chunk_end_col < end_col
250
+ # Append padding. This padding should not include background color.
251
+ chunk << "\e[0m" if has_csi
252
+ chunk << ' ' * (end_col - chunk_end_col)
253
+ chunk_end_col = end_col
254
+ end
255
+ [chunk, chunk_start_col, chunk_end_col - chunk_start_col]
202
256
  end
203
257
 
204
258
  def self.get_next_mbchar_size(line, byte_pointer)
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.5.2'
2
+ VERSION = '0.5.8'
3
3
  end
data/lib/reline.rb CHANGED
@@ -225,17 +225,20 @@ module Reline
225
225
  journey_data = completion_journey_data
226
226
  return unless journey_data
227
227
 
228
- target = journey_data.list[journey_data.pointer]
228
+ target = journey_data.list.first
229
+ completed = journey_data.list[journey_data.pointer]
229
230
  result = journey_data.list.drop(1)
230
231
  pointer = journey_data.pointer - 1
231
- return if target.empty? || (result == [target] && pointer < 0)
232
+ return if completed.empty? || (result == [completed] && pointer < 0)
232
233
 
233
234
  target_width = Reline::Unicode.calculate_width(target)
234
- x = cursor_pos.x - target_width
235
- if x < 0
236
- x = screen_width + x
235
+ completed_width = Reline::Unicode.calculate_width(completed)
236
+ if cursor_pos.x <= completed_width - target_width
237
+ # When target is rendered on the line above cursor position
238
+ x = screen_width - completed_width
237
239
  y = -1
238
240
  else
241
+ x = [cursor_pos.x - completed_width, 0].max
239
242
  y = 0
240
243
  end
241
244
  cursor_pos_to_render = Reline::CursorPos.new(x, y)
@@ -309,6 +312,10 @@ module Reline
309
312
  $stderr.sync = true
310
313
  $stderr.puts "Reline is used by #{Process.pid}"
311
314
  end
315
+ unless config.test_mode or config.loaded?
316
+ config.read
317
+ io_gate.set_default_key_bindings(config)
318
+ end
312
319
  otio = io_gate.prep
313
320
 
314
321
  may_req_ambiguous_char_width
@@ -335,12 +342,6 @@ module Reline
335
342
  end
336
343
  end
337
344
 
338
- unless config.test_mode
339
- config.read
340
- config.reset_default_key_bindings
341
- io_gate.set_default_key_bindings(config)
342
- end
343
-
344
345
  line_editor.print_nomultiline_prompt(prompt)
345
346
  line_editor.update_dialogs
346
347
  line_editor.rerender
@@ -350,7 +351,15 @@ module Reline
350
351
  loop do
351
352
  read_io(config.keyseq_timeout) { |inputs|
352
353
  line_editor.set_pasting_state(io_gate.in_pasting?)
353
- inputs.each { |key| line_editor.update(key) }
354
+ inputs.each do |key|
355
+ if key.char == :bracketed_paste_start
356
+ text = io_gate.read_bracketed_paste
357
+ line_editor.insert_pasted_text(text)
358
+ line_editor.scroll_into_view
359
+ else
360
+ line_editor.update(key)
361
+ end
362
+ end
354
363
  }
355
364
  if line_editor.finished?
356
365
  line_editor.render_finished
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.5.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-16 00:00:00.000000000 Z
11
+ date: 2024-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console
@@ -76,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
78
  requirements: []
79
- rubygems_version: 3.5.3
79
+ rubygems_version: 3.5.9
80
80
  signing_key:
81
81
  specification_version: 4
82
82
  summary: Alternative GNU Readline or Editline implementation by pure Ruby.