reline 0.5.9 → 0.5.11

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.
@@ -54,53 +54,44 @@ class Reline::Unicode
54
54
  }.join
55
55
  end
56
56
 
57
- require 'reline/unicode/east_asian_width'
57
+ def self.safe_encode(str, encoding)
58
+ # Reline only supports utf-8 convertible string.
59
+ converted = str.encode(encoding, invalid: :replace, undef: :replace)
60
+ return converted if str.encoding == Encoding::UTF_8 || converted.encoding == Encoding::UTF_8 || converted.ascii_only?
58
61
 
59
- HalfwidthDakutenHandakuten = /[\u{FF9E}\u{FF9F}]/
62
+ # This code is essentially doing the same thing as
63
+ # `str.encode(utf8, **replace_options).encode(encoding, **replace_options)`
64
+ # but also avoids unneccesary irreversible encoding conversion.
65
+ converted.gsub(/\X/) do |c|
66
+ c.encode(Encoding::UTF_8)
67
+ c
68
+ rescue Encoding::UndefinedConversionError
69
+ '?'
70
+ end
71
+ end
60
72
 
61
- MBCharWidthRE = /
62
- (?<width_2_1>
63
- [#{ EscapedChars.map {|c| "\\x%02x" % c.ord }.join }] (?# ^ + char, such as ^M, ^H, ^[, ...)
64
- )
65
- | (?<width_3>^\u{2E3B}) (?# THREE-EM DASH)
66
- | (?<width_0>^\p{M})
67
- | (?<width_2_2>
68
- #{ EastAsianWidth::TYPE_F }
69
- | #{ EastAsianWidth::TYPE_W }
70
- )
71
- | (?<width_1>
72
- #{ EastAsianWidth::TYPE_H }
73
- | #{ EastAsianWidth::TYPE_NA }
74
- | #{ EastAsianWidth::TYPE_N }
75
- )(?!#{ HalfwidthDakutenHandakuten })
76
- | (?<width_2_3>
77
- (?: #{ EastAsianWidth::TYPE_H }
78
- | #{ EastAsianWidth::TYPE_NA }
79
- | #{ EastAsianWidth::TYPE_N })
80
- #{ HalfwidthDakutenHandakuten }
81
- )
82
- | (?<ambiguous_width>
83
- #{EastAsianWidth::TYPE_A}
84
- )
85
- /x
73
+ require 'reline/unicode/east_asian_width'
86
74
 
87
75
  def self.get_mbchar_width(mbchar)
88
76
  ord = mbchar.ord
89
- if (0x00 <= ord and ord <= 0x1F) # in EscapedPairs
77
+ if ord <= 0x1F # in EscapedPairs
90
78
  return 2
91
- elsif (0x20 <= ord and ord <= 0x7E) # printable ASCII chars
79
+ elsif ord <= 0x7E # printable ASCII chars
92
80
  return 1
93
81
  end
94
- m = mbchar.encode(Encoding::UTF_8).match(MBCharWidthRE)
95
- case
96
- when m.nil? then 1 # TODO should be U+FFFD � REPLACEMENT CHARACTER
97
- when m[:width_2_1], m[:width_2_2], m[:width_2_3] then 2
98
- when m[:width_3] then 3
99
- when m[:width_0] then 0
100
- when m[:width_1] then 1
101
- when m[:ambiguous_width] then Reline.ambiguous_width
82
+ utf8_mbchar = mbchar.encode(Encoding::UTF_8)
83
+ ord = utf8_mbchar.ord
84
+ chunk_index = EastAsianWidth::CHUNK_LAST.bsearch_index { |o| ord <= o }
85
+ size = EastAsianWidth::CHUNK_WIDTH[chunk_index]
86
+ if size == -1
87
+ Reline.ambiguous_width
88
+ elsif size == 1 && utf8_mbchar.size >= 2
89
+ second_char_ord = utf8_mbchar[1].ord
90
+ # Halfwidth Dakuten Handakuten
91
+ # Only these two character has Letter Modifier category and can be combined in a single grapheme cluster
92
+ (second_char_ord == 0xFF9E || second_char_ord == 0xFF9F) ? 2 : 1
102
93
  else
103
- nil
94
+ size
104
95
  end
105
96
  end
106
97
 
@@ -141,10 +132,8 @@ class Reline::Unicode
141
132
  case
142
133
  when non_printing_start
143
134
  in_zero_width = true
144
- lines.last << NON_PRINTING_START
145
135
  when non_printing_end
146
136
  in_zero_width = false
147
- lines.last << NON_PRINTING_END
148
137
  when csi
149
138
  lines.last << csi
150
139
  unless in_zero_width
@@ -156,7 +145,7 @@ class Reline::Unicode
156
145
  end
157
146
  when osc
158
147
  lines.last << osc
159
- seq << osc
148
+ seq << osc unless in_zero_width
160
149
  when gc
161
150
  unless in_zero_width
162
151
  mbchar_width = get_mbchar_width(gc)
@@ -179,6 +168,10 @@ class Reline::Unicode
179
168
  [lines, height]
180
169
  end
181
170
 
171
+ def self.strip_non_printing_start_end(prompt)
172
+ prompt.gsub(/\x01([^\x02]*)(?:\x02|\z)/) { $1 }
173
+ end
174
+
182
175
  # Take a chunk of a String cut by width with escape sequences.
183
176
  def self.take_range(str, start_col, max_width)
184
177
  take_mbchar_range(str, start_col, max_width).first
@@ -198,10 +191,8 @@ class Reline::Unicode
198
191
  case
199
192
  when non_printing_start
200
193
  in_zero_width = true
201
- chunk << NON_PRINTING_START
202
194
  when non_printing_end
203
195
  in_zero_width = false
204
- chunk << NON_PRINTING_END
205
196
  when csi
206
197
  has_csi = true
207
198
  chunk << csi
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.5.9'
2
+ VERSION = '0.5.11'
3
3
  end
data/lib/reline.rb CHANGED
@@ -308,7 +308,7 @@ module Reline
308
308
  otio = io_gate.prep
309
309
 
310
310
  may_req_ambiguous_char_width
311
- line_editor.reset(prompt, encoding: encoding)
311
+ line_editor.reset(prompt)
312
312
  if multiline
313
313
  line_editor.multiline_on
314
314
  if block_given?
@@ -324,14 +324,17 @@ module Reline
324
324
  line_editor.prompt_proc = prompt_proc
325
325
  line_editor.auto_indent_proc = auto_indent_proc
326
326
  line_editor.dig_perfect_match_proc = dig_perfect_match_proc
327
+
328
+ # Readline calls pre_input_hook just after printing the first prompt.
329
+ line_editor.print_nomultiline_prompt
327
330
  pre_input_hook&.call
331
+
328
332
  unless Reline::IOGate.dumb?
329
333
  @dialog_proc_list.each_pair do |name_sym, d|
330
334
  line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
331
335
  end
332
336
  end
333
337
 
334
- line_editor.print_nomultiline_prompt(prompt)
335
338
  line_editor.update_dialogs
336
339
  line_editor.rerender
337
340
 
@@ -343,7 +346,7 @@ module Reline
343
346
  inputs.each do |key|
344
347
  if key.char == :bracketed_paste_start
345
348
  text = io_gate.read_bracketed_paste
346
- line_editor.insert_pasted_text(text)
349
+ line_editor.insert_multiline_text(text)
347
350
  line_editor.scroll_into_view
348
351
  else
349
352
  line_editor.update(key)
@@ -409,7 +412,7 @@ module Reline
409
412
  end
410
413
 
411
414
  private def may_req_ambiguous_char_width
412
- @ambiguous_width = 2 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
415
+ @ambiguous_width = 1 if io_gate.dumb? || !STDIN.tty? || !STDOUT.tty?
413
416
  return if defined? @ambiguous_width
414
417
  io_gate.move_cursor_column(0)
415
418
  begin
@@ -418,7 +421,7 @@ module Reline
418
421
  # LANG=C
419
422
  @ambiguous_width = 1
420
423
  else
421
- @ambiguous_width = io_gate.cursor_pos.x
424
+ @ambiguous_width = io_gate.cursor_pos.x == 2 ? 2 : 1
422
425
  end
423
426
  io_gate.move_cursor_column(0)
424
427
  io_gate.erase_after_cursor
@@ -457,8 +460,8 @@ module Reline
457
460
  def_single_delegator :line_editor, :byte_pointer, :point
458
461
  def_single_delegator :line_editor, :byte_pointer=, :point=
459
462
 
460
- def self.insert_text(*args, &block)
461
- line_editor.insert_text(*args, &block)
463
+ def self.insert_text(text)
464
+ line_editor.insert_multiline_text(text)
462
465
  self
463
466
  end
464
467
 
@@ -484,7 +487,7 @@ module Reline
484
487
  @core ||= Core.new { |core|
485
488
  core.config = Reline::Config.new
486
489
  core.key_stroke = Reline::KeyStroke.new(core.config)
487
- core.line_editor = Reline::LineEditor.new(core.config, core.encoding)
490
+ core.line_editor = Reline::LineEditor.new(core.config)
488
491
 
489
492
  core.basic_word_break_characters = " \t\n`><=;|&{("
490
493
  core.completer_word_break_characters = " \t\n`><=;|&{("
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.9
4
+ version: 0.5.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-06-12 00:00:00.000000000 Z
10
+ date: 2024-11-08 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: io-console
@@ -63,7 +62,6 @@ metadata:
63
62
  bug_tracker_uri: https://github.com/ruby/reline/issues
64
63
  changelog_uri: https://github.com/ruby/reline/releases
65
64
  source_code_uri: https://github.com/ruby/reline
66
- post_install_message:
67
65
  rdoc_options: []
68
66
  require_paths:
69
67
  - lib
@@ -78,8 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
76
  - !ruby/object:Gem::Version
79
77
  version: '0'
80
78
  requirements: []
81
- rubygems_version: 3.5.9
82
- signing_key:
79
+ rubygems_version: 3.6.0.dev
83
80
  specification_version: 4
84
81
  summary: Alternative GNU Readline or Editline implementation by pure Ruby.
85
82
  test_files: []