reline 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77e916d771c2f7219d8cba4be2e3b5e6102dddcb505b342375b8717e069caab1
4
- data.tar.gz: ec4262c712ed77b4807255d12887542b37e74cf0e1ccf1dfef78d803d886ba17
3
+ metadata.gz: 45922535b3972631020c6b33bc6b88fd400062fb2c0820ab95ab991704c1fc42
4
+ data.tar.gz: 53f36ad5e7e196ba34a22990c32b38556653b7384bd99108a791d1b4c7cd3b36
5
5
  SHA512:
6
- metadata.gz: b0b88eb00ce703b01f691c2fc780a7f9ff43fefdcc9d42d22122bba742ddc03b20db19ecca2c21082081f66d4993f70a3a4cb53ea50ed5a0255728635360c45c
7
- data.tar.gz: eb4b51fb15f94e2c349fe4cf19c2d6426f7fdf0800320b89a14d66e6f18ea72f327d7792a8edb6d6034df708bb7c25fbffb625fe7cc03271efdb6662d9c90deb
6
+ metadata.gz: eb1b50add8dc60baeefd1fecce83abbaf0e134c16c30ca7fd268efe46d364638280bd2a16100e54be6dbf691bc8a9d4220c53210233a06a0278361c07bd5a56f
7
+ data.tar.gz: 5ed4f57373cd6e9329de58b9361037e4f8e510020c0ba59970de5733a8c8f4b5c004b871d8e21f013ee065daed9b55f433142529b5e4039276a0f0adbc00c4d9
data/lib/reline/ansi.rb CHANGED
@@ -284,7 +284,7 @@ class Reline::ANSI
284
284
  buf = @@output.pread(@@output.pos, 0)
285
285
  row = buf.count("\n")
286
286
  column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0
287
- rescue Errno::ESPIPE
287
+ rescue Errno::ESPIPE, IOError
288
288
  # Just returns column 1 for ambiguous width because this I/O is not
289
289
  # tty and can't seek.
290
290
  row = 0
data/lib/reline/config.rb CHANGED
@@ -53,8 +53,6 @@ class Reline::Config
53
53
  @additional_key_bindings[:vi_insert] = {}
54
54
  @additional_key_bindings[:vi_command] = {}
55
55
  @oneshot_key_bindings = {}
56
- @skip_section = nil
57
- @if_stack = nil
58
56
  @editing_mode_label = :emacs
59
57
  @keymap_label = :emacs
60
58
  @keymap_prefix = []
@@ -190,9 +188,7 @@ class Reline::Config
190
188
  end
191
189
  end
192
190
  end
193
- conditions = [@skip_section, @if_stack]
194
- @skip_section = nil
195
- @if_stack = []
191
+ if_stack = []
196
192
 
197
193
  lines.each_with_index do |line, no|
198
194
  next if line.match(/\A\s*#/)
@@ -201,11 +197,11 @@ class Reline::Config
201
197
 
202
198
  line = line.chomp.lstrip
203
199
  if line.start_with?('$')
204
- handle_directive(line[1..-1], file, no)
200
+ handle_directive(line[1..-1], file, no, if_stack)
205
201
  next
206
202
  end
207
203
 
208
- next if @skip_section
204
+ next if if_stack.any? { |_no, skip| skip }
209
205
 
210
206
  case line
211
207
  when /^set +([^ ]+) +([^ ]+)/i
@@ -214,43 +210,47 @@ class Reline::Config
214
210
  next
215
211
  when /\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o
216
212
  key, func_name = $1, $2
213
+ func_name = func_name.split.first
217
214
  keystroke, func = bind_key(key, func_name)
218
215
  next unless keystroke
219
216
  @additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
220
217
  end
221
218
  end
222
- unless @if_stack.empty?
223
- raise InvalidInputrc, "#{file}:#{@if_stack.last[1]}: unclosed if"
219
+ unless if_stack.empty?
220
+ raise InvalidInputrc, "#{file}:#{if_stack.last[0]}: unclosed if"
224
221
  end
225
- ensure
226
- @skip_section, @if_stack = conditions
227
222
  end
228
223
 
229
- def handle_directive(directive, file, no)
224
+ def handle_directive(directive, file, no, if_stack)
230
225
  directive, args = directive.split(' ')
231
226
  case directive
232
227
  when 'if'
233
228
  condition = false
234
229
  case args
235
- when 'mode'
230
+ when /^mode=(vi|emacs)$/i
231
+ mode = $1.downcase
232
+ # NOTE: mode=vi means vi-insert mode
233
+ mode = 'vi_insert' if mode == 'vi'
234
+ if @editing_mode_label == mode.to_sym
235
+ condition = true
236
+ end
236
237
  when 'term'
237
238
  when 'version'
238
239
  else # application name
239
240
  condition = true if args == 'Ruby'
240
241
  condition = true if args == 'Reline'
241
242
  end
242
- @if_stack << [file, no, @skip_section]
243
- @skip_section = !condition
243
+ if_stack << [no, !condition]
244
244
  when 'else'
245
- if @if_stack.empty?
245
+ if if_stack.empty?
246
246
  raise InvalidInputrc, "#{file}:#{no}: unmatched else"
247
247
  end
248
- @skip_section = !@skip_section
248
+ if_stack.last[1] = !if_stack.last[1]
249
249
  when 'endif'
250
- if @if_stack.empty?
250
+ if if_stack.empty?
251
251
  raise InvalidInputrc, "#{file}:#{no}: unmatched endif"
252
252
  end
253
- @skip_section = @if_stack.pop
253
+ if_stack.pop
254
254
  when 'include'
255
255
  read(File.expand_path(args))
256
256
  end
@@ -414,8 +414,13 @@ class Reline::LineEditor
414
414
  @output.write "#{Reline::IOGate::RESET_COLOR}#{' ' * width}"
415
415
  else
416
416
  x, w, content = new_items[level]
417
- content = Reline::Unicode.take_range(content, base_x - x, width) unless x == base_x && w == width
418
- Reline::IOGate.move_cursor_column base_x
417
+ cover_begin = base_x != 0 && new_levels[base_x - 1] == level
418
+ cover_end = new_levels[base_x + width] == level
419
+ pos = 0
420
+ unless x == base_x && w == width
421
+ content, pos = Reline::Unicode.take_mbchar_range(content, base_x - x, width, cover_begin: cover_begin, cover_end: cover_end, padding: true)
422
+ end
423
+ Reline::IOGate.move_cursor_column x + pos
419
424
  @output.write "#{Reline::IOGate::RESET_COLOR}#{content}#{Reline::IOGate::RESET_COLOR}"
420
425
  end
421
426
  base_x += width
@@ -699,13 +704,6 @@ class Reline::LineEditor
699
704
 
700
705
  DIALOG_DEFAULT_HEIGHT = 20
701
706
 
702
- private def padding_space_with_escape_sequences(str, width)
703
- padding_width = width - calculate_width(str, true)
704
- # padding_width should be only positive value. But macOS and Alacritty returns negative value.
705
- padding_width = 0 if padding_width < 0
706
- str + (' ' * padding_width)
707
- end
708
-
709
707
  private def dialog_range(dialog, dialog_y)
710
708
  x_range = dialog.column...dialog.column + dialog.width
711
709
  y_range = dialog_y + dialog.vertical_offset...dialog_y + dialog.vertical_offset + dialog.contents.size
@@ -778,7 +776,7 @@ class Reline::LineEditor
778
776
  dialog.contents = contents.map.with_index do |item, i|
779
777
  line_sgr = i == pointer ? enhanced_sgr : default_sgr
780
778
  str_width = dialog.width - (scrollbar_pos.nil? ? 0 : @block_elem_width)
781
- str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, str_width), str_width)
779
+ str, = Reline::Unicode.take_mbchar_range(item, 0, str_width, padding: true)
782
780
  colored_content = "#{line_sgr}#{str}"
783
781
  if scrollbar_pos
784
782
  if scrollbar_pos <= (i * 2) and (i * 2 + 1) < (scrollbar_pos + bar_height)
@@ -1120,6 +1118,7 @@ class Reline::LineEditor
1120
1118
  end
1121
1119
  end
1122
1120
  if key.char.nil?
1121
+ process_insert(force: true)
1123
1122
  if @first_char
1124
1123
  @eof = true
1125
1124
  end
@@ -1542,11 +1541,7 @@ class Reline::LineEditor
1542
1541
  alias_method :vi_zero, :ed_move_to_beg
1543
1542
 
1544
1543
  private def ed_move_to_end(key)
1545
- @byte_pointer = 0
1546
- while @byte_pointer < current_line.bytesize
1547
- byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
1548
- @byte_pointer += byte_size
1549
- end
1544
+ @byte_pointer = current_line.bytesize
1550
1545
  end
1551
1546
  alias_method :end_of_line, :ed_move_to_end
1552
1547
 
@@ -145,7 +145,13 @@ class Reline::Unicode
145
145
  lines.last << NON_PRINTING_END
146
146
  when csi
147
147
  lines.last << csi
148
- seq << csi
148
+ unless in_zero_width
149
+ if csi == -"\e[m" || csi == -"\e[0m"
150
+ seq.clear
151
+ else
152
+ seq << csi
153
+ end
154
+ end
149
155
  when osc
150
156
  lines.last << osc
151
157
  seq << osc
@@ -173,32 +179,78 @@ class Reline::Unicode
173
179
 
174
180
  # Take a chunk of a String cut by width with escape sequences.
175
181
  def self.take_range(str, start_col, max_width)
182
+ take_mbchar_range(str, start_col, max_width).first
183
+ end
184
+
185
+ def self.take_mbchar_range(str, start_col, width, cover_begin: false, cover_end: false, padding: false)
176
186
  chunk = String.new(encoding: str.encoding)
187
+
188
+ end_col = start_col + width
177
189
  total_width = 0
178
190
  rest = str.encode(Encoding::UTF_8)
179
191
  in_zero_width = false
192
+ chunk_start_col = nil
193
+ chunk_end_col = nil
194
+ has_csi = false
180
195
  rest.scan(WIDTH_SCANNER) do |non_printing_start, non_printing_end, csi, osc, gc|
181
196
  case
182
197
  when non_printing_start
183
198
  in_zero_width = true
199
+ chunk << NON_PRINTING_START
184
200
  when non_printing_end
185
201
  in_zero_width = false
202
+ chunk << NON_PRINTING_END
186
203
  when csi
204
+ has_csi = true
187
205
  chunk << csi
188
206
  when osc
189
207
  chunk << osc
190
208
  when gc
191
209
  if in_zero_width
192
210
  chunk << gc
211
+ next
212
+ end
213
+
214
+ mbchar_width = get_mbchar_width(gc)
215
+ prev_width = total_width
216
+ total_width += mbchar_width
217
+
218
+ if (cover_begin || padding ? total_width <= start_col : prev_width < start_col)
219
+ # Current character haven't reached start_col yet
220
+ next
221
+ elsif padding && !cover_begin && prev_width < start_col && start_col < total_width
222
+ # Add preceding padding. This padding might have background color.
223
+ chunk << ' '
224
+ chunk_start_col ||= start_col
225
+ chunk_end_col = total_width
226
+ next
227
+ elsif (cover_end ? prev_width < end_col : total_width <= end_col)
228
+ # Current character is in the range
229
+ chunk << gc
230
+ chunk_start_col ||= prev_width
231
+ chunk_end_col = total_width
232
+ break if total_width >= end_col
193
233
  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
234
+ # Current character exceeds end_col
235
+ if padding && end_col < total_width
236
+ # Add succeeding padding. This padding might have background color.
237
+ chunk << ' '
238
+ chunk_start_col ||= prev_width
239
+ chunk_end_col = end_col
240
+ end
241
+ break
198
242
  end
199
243
  end
200
244
  end
201
- chunk
245
+ chunk_start_col ||= start_col
246
+ chunk_end_col ||= start_col
247
+ if padding && chunk_end_col < end_col
248
+ # Append padding. This padding should not include background color.
249
+ chunk << "\e[0m" if has_csi
250
+ chunk << ' ' * (end_col - chunk_end_col)
251
+ chunk_end_col = end_col
252
+ end
253
+ [chunk, chunk_start_col, chunk_end_col - chunk_start_col]
202
254
  end
203
255
 
204
256
  def self.get_next_mbchar_size(line, byte_pointer)
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.5.3'
2
+ VERSION = '0.5.4'
3
3
  end
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.3
4
+ version: 0.5.4
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-23 00:00:00.000000000 Z
11
+ date: 2024-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console