reline 0.5.8 → 0.5.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,138 +7,99 @@ class Reline::KeyStroke
7
7
  @config = config
8
8
  end
9
9
 
10
- def compress_meta_key(ary)
11
- return ary unless @config.convert_meta
12
- ary.inject([]) { |result, key|
13
- if result.size > 0 and result.last == "\e".ord
14
- result[result.size - 1] = Reline::Key.new(key, key | 0b10000000, true)
15
- else
16
- result << key
17
- end
18
- result
19
- }
20
- end
10
+ # Input exactly matches to a key sequence
11
+ MATCHING = :matching
12
+ # Input partially matches to a key sequence
13
+ MATCHED = :matched
14
+ # Input matches to a key sequence and the key sequence is a prefix of another key sequence
15
+ MATCHING_MATCHED = :matching_matched
16
+ # Input does not match to any key sequence
17
+ UNMATCHED = :unmatched
21
18
 
22
- def start_with?(me, other)
23
- compressed_me = compress_meta_key(me)
24
- compressed_other = compress_meta_key(other)
25
- i = 0
26
- loop do
27
- my_c = compressed_me[i]
28
- other_c = compressed_other[i]
29
- other_is_last = (i + 1) == compressed_other.size
30
- me_is_last = (i + 1) == compressed_me.size
31
- if my_c != other_c
32
- if other_c == "\e".ord and other_is_last and my_c.is_a?(Reline::Key) and my_c.with_meta
33
- return true
34
- else
35
- return false
36
- end
37
- elsif other_is_last
38
- return true
39
- elsif me_is_last
40
- return false
41
- end
42
- i += 1
43
- end
44
- end
19
+ def match_status(input)
20
+ matching = key_mapping.matching?(input)
21
+ matched = key_mapping.get(input)
45
22
 
46
- def equal?(me, other)
47
- case me
48
- when Array
49
- compressed_me = compress_meta_key(me)
50
- compressed_other = compress_meta_key(other)
51
- compressed_me.size == compressed_other.size and [compressed_me, compressed_other].transpose.all?{ |i| equal?(i[0], i[1]) }
52
- when Integer
53
- if other.is_a?(Reline::Key)
54
- if other.combined_char == "\e".ord
55
- false
56
- else
57
- other.combined_char == me
58
- end
59
- else
60
- me == other
61
- end
62
- when Reline::Key
63
- if other.is_a?(Integer)
64
- me.combined_char == other
65
- else
66
- me == other
67
- end
68
- end
69
- end
23
+ # FIXME: Workaround for single byte. remove this after MAPPING is merged into KeyActor.
24
+ matched ||= input.size == 1
25
+ matching ||= input == [ESC_BYTE]
70
26
 
71
- def match_status(input)
72
- key_mapping.keys.select { |lhs|
73
- start_with?(lhs, input)
74
- }.tap { |it|
75
- return :matched if it.size == 1 && equal?(it[0], input)
76
- return :matching if it.size == 1 && !equal?(it[0], input)
77
- return :matched if it.max_by(&:size)&.size&.< input.size
78
- return :matching if it.size > 1
79
- }
80
- if key_mapping.keys.any? { |lhs| start_with?(input, lhs) }
81
- :matched
27
+ if matching && matched
28
+ MATCHING_MATCHED
29
+ elsif matching
30
+ MATCHING
31
+ elsif matched
32
+ MATCHED
33
+ elsif input[0] == ESC_BYTE
34
+ match_unknown_escape_sequence(input, vi_mode: @config.editing_mode_is?(:vi_insert, :vi_command))
35
+ elsif input.size == 1
36
+ MATCHED
82
37
  else
83
- match_unknown_escape_sequence(input).first
38
+ UNMATCHED
84
39
  end
85
40
  end
86
41
 
87
42
  def expand(input)
88
- lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
89
- unless lhs
90
- status, size = match_unknown_escape_sequence(input)
91
- case status
92
- when :matched
93
- return [:ed_unassigned] + expand(input.drop(size))
94
- when :matching
95
- return [:ed_unassigned]
96
- else
97
- return input
98
- end
43
+ matched_bytes = nil
44
+ (1..input.size).each do |i|
45
+ bytes = input.take(i)
46
+ status = match_status(bytes)
47
+ matched_bytes = bytes if status == MATCHED || status == MATCHING_MATCHED
99
48
  end
100
- rhs = key_mapping[lhs]
49
+ return [[], []] unless matched_bytes
101
50
 
102
- case rhs
103
- when String
104
- rhs_bytes = rhs.bytes
105
- expand(expand(rhs_bytes) + expand(input.drop(lhs.size)))
106
- when Symbol
107
- [rhs] + expand(input.drop(lhs.size))
108
- when Array
109
- rhs
51
+ func = key_mapping.get(matched_bytes)
52
+ if func.is_a?(Array)
53
+ keys = func.map { |c| Reline::Key.new(c, c, false) }
54
+ elsif func
55
+ keys = [Reline::Key.new(func, func, false)]
56
+ elsif matched_bytes.size == 1
57
+ keys = [Reline::Key.new(matched_bytes.first, matched_bytes.first, false)]
58
+ elsif matched_bytes.size == 2 && matched_bytes[0] == ESC_BYTE
59
+ keys = [Reline::Key.new(matched_bytes[1], matched_bytes[1] | 0b10000000, true)]
60
+ else
61
+ keys = []
110
62
  end
63
+
64
+ [keys, input.drop(matched_bytes.size)]
111
65
  end
112
66
 
113
67
  private
114
68
 
115
69
  # returns match status of CSI/SS3 sequence and matched length
116
- def match_unknown_escape_sequence(input)
70
+ def match_unknown_escape_sequence(input, vi_mode: false)
117
71
  idx = 0
118
- return [:unmatched, nil] unless input[idx] == ESC_BYTE
72
+ return UNMATCHED unless input[idx] == ESC_BYTE
119
73
  idx += 1
120
74
  idx += 1 if input[idx] == ESC_BYTE
121
75
 
122
76
  case input[idx]
123
77
  when nil
124
- return [:matching, nil]
78
+ if idx == 1 # `ESC`
79
+ return MATCHING_MATCHED
80
+ else # `ESC ESC`
81
+ return MATCHING
82
+ end
125
83
  when 91 # == '['.ord
126
- # CSI sequence
84
+ # CSI sequence `ESC [ ... char`
127
85
  idx += 1
128
86
  idx += 1 while idx < input.size && CSI_PARAMETER_BYTES_RANGE.cover?(input[idx])
129
87
  idx += 1 while idx < input.size && CSI_INTERMEDIATE_BYTES_RANGE.cover?(input[idx])
130
- input[idx] ? [:matched, idx + 1] : [:matching, nil]
131
88
  when 79 # == 'O'.ord
132
- # SS3 sequence
133
- input[idx + 1] ? [:matched, idx + 2] : [:matching, nil]
89
+ # SS3 sequence `ESC O char`
90
+ idx += 1
134
91
  else
135
- if idx == 1
136
- # `ESC char`, make it :unmatched so that it will be handled correctly in `read_2nd_character_of_key_sequence`
137
- [:unmatched, nil]
138
- else
139
- # `ESC ESC char`
140
- [:matched, idx + 1]
141
- end
92
+ # `ESC char` or `ESC ESC char`
93
+ return UNMATCHED if vi_mode
94
+ end
95
+
96
+ case input.size
97
+ when idx
98
+ MATCHING
99
+ when idx + 1
100
+ MATCHED
101
+ else
102
+ UNMATCHED
142
103
  end
143
104
  end
144
105
 
@@ -45,6 +45,7 @@ class Reline::LineEditor
45
45
  RenderedScreen = Struct.new(:base_y, :lines, :cursor_y, keyword_init: true)
46
46
 
47
47
  CompletionJourneyState = Struct.new(:line_index, :pre, :target, :post, :list, :pointer)
48
+ NullActionState = [nil, nil].freeze
48
49
 
49
50
  class MenuInfo
50
51
  attr_reader :list
@@ -175,9 +176,8 @@ class Reline::LineEditor
175
176
  scroll_into_view
176
177
  Reline::IOGate.move_cursor_up @rendered_screen.cursor_y
177
178
  @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
178
- @rendered_screen.lines = []
179
- @rendered_screen.cursor_y = 0
180
- render_differential
179
+ clear_rendered_screen_cache
180
+ render
181
181
  end
182
182
 
183
183
  private def handle_interrupted
@@ -185,11 +185,11 @@ class Reline::LineEditor
185
185
 
186
186
  @interrupted = false
187
187
  clear_dialogs
188
- scrolldown = render_differential
189
- Reline::IOGate.scroll_down scrolldown
188
+ render
189
+ cursor_to_bottom_offset = @rendered_screen.lines.size - @rendered_screen.cursor_y
190
+ Reline::IOGate.scroll_down cursor_to_bottom_offset
190
191
  Reline::IOGate.move_cursor_column 0
191
- @rendered_screen.lines = []
192
- @rendered_screen.cursor_y = 0
192
+ clear_rendered_screen_cache
193
193
  case @old_trap
194
194
  when 'DEFAULT', 'SYSTEM_DEFAULT'
195
195
  raise Interrupt
@@ -237,7 +237,6 @@ class Reline::LineEditor
237
237
  @perfect_matched = nil
238
238
  @menu_info = nil
239
239
  @searching_prompt = nil
240
- @first_char = true
241
240
  @just_cursor_moving = false
242
241
  @eof = false
243
242
  @continuous_insertion_buffer = String.new(encoding: @encoding)
@@ -253,6 +252,8 @@ class Reline::LineEditor
253
252
  @input_lines = [[[""], 0, 0]]
254
253
  @input_lines_position = 0
255
254
  @undoing = false
255
+ @prev_action_state = NullActionState
256
+ @next_action_state = NullActionState
256
257
  reset_line
257
258
  end
258
259
 
@@ -412,7 +413,7 @@ class Reline::LineEditor
412
413
  # do nothing
413
414
  elsif level == :blank
414
415
  Reline::IOGate.move_cursor_column base_x
415
- @output.write "#{Reline::IOGate::RESET_COLOR}#{' ' * width}"
416
+ @output.write "#{Reline::IOGate.reset_color_sequence}#{' ' * width}"
416
417
  else
417
418
  x, w, content = new_items[level]
418
419
  cover_begin = base_x != 0 && new_levels[base_x - 1] == level
@@ -422,7 +423,7 @@ class Reline::LineEditor
422
423
  content, pos = Reline::Unicode.take_mbchar_range(content, base_x - x, width, cover_begin: cover_begin, cover_end: cover_end, padding: true)
423
424
  end
424
425
  Reline::IOGate.move_cursor_column x + pos
425
- @output.write "#{Reline::IOGate::RESET_COLOR}#{content}#{Reline::IOGate::RESET_COLOR}"
426
+ @output.write "#{Reline::IOGate.reset_color_sequence}#{content}#{Reline::IOGate.reset_color_sequence}"
426
427
  end
427
428
  base_x += width
428
429
  end
@@ -458,28 +459,7 @@ class Reline::LineEditor
458
459
  end
459
460
 
460
461
  def render_finished
461
- clear_rendered_lines
462
- render_full_content
463
- end
464
-
465
- def clear_rendered_lines
466
- Reline::IOGate.move_cursor_up @rendered_screen.cursor_y
467
- Reline::IOGate.move_cursor_column 0
468
-
469
- num_lines = @rendered_screen.lines.size
470
- return unless num_lines && num_lines >= 1
471
-
472
- Reline::IOGate.move_cursor_down num_lines - 1
473
- (num_lines - 1).times do
474
- Reline::IOGate.erase_after_cursor
475
- Reline::IOGate.move_cursor_up 1
476
- end
477
- Reline::IOGate.erase_after_cursor
478
- @rendered_screen.lines = []
479
- @rendered_screen.cursor_y = 0
480
- end
481
-
482
- def render_full_content
462
+ render_differential([], 0, 0)
483
463
  lines = @buffer_of_lines.size.times.map do |i|
484
464
  line = prompt_list[i] + modified_lines[i]
485
465
  wrapped_lines, = split_by_width(line, screen_width)
@@ -488,19 +468,13 @@ class Reline::LineEditor
488
468
  @output.puts lines.map { |l| "#{l}\r\n" }.join
489
469
  end
490
470
 
491
- def print_nomultiline_prompt(prompt)
492
- return unless prompt && !@is_multiline
493
-
471
+ def print_nomultiline_prompt
494
472
  # Readline's test `TestRelineAsReadline#test_readline` requires first output to be prompt, not cursor reset escape sequence.
495
- @rendered_screen.lines = [[[0, Reline::Unicode.calculate_width(prompt, true), prompt]]]
496
- @rendered_screen.cursor_y = 0
497
- @output.write prompt
473
+ @output.write @prompt if @prompt && !@is_multiline
498
474
  end
499
475
 
500
- def render_differential
476
+ def render
501
477
  wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
502
-
503
- rendered_lines = @rendered_screen.lines
504
478
  new_lines = wrapped_prompt_and_input_lines.flatten(1)[screen_scroll_top, screen_height].map do |prompt, line|
505
479
  prompt_width = Reline::Unicode.calculate_width(prompt, true)
506
480
  [[0, prompt_width, prompt], [prompt_width, Reline::Unicode.calculate_width(line, true), line]]
@@ -518,12 +492,21 @@ class Reline::LineEditor
518
492
  x_range, y_range = dialog_range dialog, wrapped_cursor_y - screen_scroll_top
519
493
  y_range.each do |row|
520
494
  next if row < 0 || row >= screen_height
495
+
521
496
  dialog_rows = new_lines[row] ||= []
522
497
  # index 0 is for prompt, index 1 is for line, index 2.. is for dialog
523
498
  dialog_rows[index + 2] = [x_range.begin, dialog.width, dialog.contents[row - y_range.begin]]
524
499
  end
525
500
  end
526
501
 
502
+ render_differential new_lines, wrapped_cursor_x, wrapped_cursor_y - screen_scroll_top
503
+ end
504
+
505
+ # Reflects lines to be rendered and new cursor position to the screen
506
+ # by calculating the difference from the previous render.
507
+
508
+ private def render_differential(new_lines, new_cursor_x, new_cursor_y)
509
+ rendered_lines = @rendered_screen.lines
527
510
  cursor_y = @rendered_screen.cursor_y
528
511
  if new_lines != rendered_lines
529
512
  # Hide cursor while rendering to avoid cursor flickering.
@@ -550,11 +533,14 @@ class Reline::LineEditor
550
533
  @rendered_screen.lines = new_lines
551
534
  Reline::IOGate.show_cursor
552
535
  end
553
- y = wrapped_cursor_y - screen_scroll_top
554
- Reline::IOGate.move_cursor_column wrapped_cursor_x
555
- Reline::IOGate.move_cursor_down y - cursor_y
556
- @rendered_screen.cursor_y = y
557
- new_lines.size - y
536
+ Reline::IOGate.move_cursor_column new_cursor_x
537
+ Reline::IOGate.move_cursor_down new_cursor_y - cursor_y
538
+ @rendered_screen.cursor_y = new_cursor_y
539
+ end
540
+
541
+ private def clear_rendered_screen_cache
542
+ @rendered_screen.lines = []
543
+ @rendered_screen.cursor_y = 0
558
544
  end
559
545
 
560
546
  def upper_space_height(wrapped_cursor_y)
@@ -566,7 +552,7 @@ class Reline::LineEditor
566
552
  end
567
553
 
568
554
  def rerender
569
- render_differential unless @in_pasting
555
+ render unless @in_pasting
570
556
  end
571
557
 
572
558
  class DialogProcScope
@@ -684,10 +670,8 @@ class Reline::LineEditor
684
670
  @trap_key.each do |t|
685
671
  @config.add_oneshot_key_binding(t, @name)
686
672
  end
687
- elsif @trap_key.is_a?(Array)
673
+ else
688
674
  @config.add_oneshot_key_binding(@trap_key, @name)
689
- elsif @trap_key.is_a?(Integer) or @trap_key.is_a?(Reline::Key)
690
- @config.add_oneshot_key_binding([@trap_key], @name)
691
675
  end
692
676
  end
693
677
  dialog_render_info
@@ -1080,17 +1064,7 @@ class Reline::LineEditor
1080
1064
  else # single byte
1081
1065
  return if key.char >= 128 # maybe, first byte of multi byte
1082
1066
  method_symbol = @config.editing_mode.get_method(key.combined_char)
1083
- if key.with_meta and method_symbol == :ed_unassigned
1084
- if @config.editing_mode_is?(:vi_command, :vi_insert)
1085
- # split ESC + key in vi mode
1086
- method_symbol = @config.editing_mode.get_method("\e".ord)
1087
- process_key("\e".ord, method_symbol)
1088
- method_symbol = @config.editing_mode.get_method(key.char)
1089
- process_key(key.char, method_symbol)
1090
- end
1091
- else
1092
- process_key(key.combined_char, method_symbol)
1093
- end
1067
+ process_key(key.combined_char, method_symbol)
1094
1068
  @multibyte_buffer.clear
1095
1069
  end
1096
1070
  if @config.editing_mode_is?(:vi_command) and @byte_pointer > 0 and @byte_pointer == current_line.bytesize
@@ -1119,13 +1093,10 @@ class Reline::LineEditor
1119
1093
  end
1120
1094
  if key.char.nil?
1121
1095
  process_insert(force: true)
1122
- if @first_char
1123
- @eof = true
1124
- end
1096
+ @eof = buffer_empty?
1125
1097
  finish
1126
1098
  return
1127
1099
  end
1128
- @first_char = false
1129
1100
  @completion_occurs = false
1130
1101
 
1131
1102
  if key.char.is_a?(Symbol)
@@ -1133,6 +1104,9 @@ class Reline::LineEditor
1133
1104
  else
1134
1105
  normal_char(key)
1135
1106
  end
1107
+
1108
+ @prev_action_state, @next_action_state = @next_action_state, NullActionState
1109
+
1136
1110
  unless @completion_occurs
1137
1111
  @completion_state = CompletionState::NORMAL
1138
1112
  @completion_journey_state = nil
@@ -1347,7 +1321,7 @@ class Reline::LineEditor
1347
1321
  @confirm_multiline_termination_proc.(temp_buffer.join("\n") + "\n")
1348
1322
  end
1349
1323
 
1350
- def insert_pasted_text(text)
1324
+ def insert_multiline_text(text)
1351
1325
  save_old_buffer
1352
1326
  pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer)
1353
1327
  post = @buffer_of_lines[@line_index].byteslice(@byte_pointer..)
@@ -1415,6 +1389,10 @@ class Reline::LineEditor
1415
1389
  whole_lines.join("\n")
1416
1390
  end
1417
1391
 
1392
+ private def buffer_empty?
1393
+ current_line.empty? and @buffer_of_lines.size == 1
1394
+ end
1395
+
1418
1396
  def finished?
1419
1397
  @finished
1420
1398
  end
@@ -1763,29 +1741,31 @@ class Reline::LineEditor
1763
1741
  end
1764
1742
 
1765
1743
  private def ed_search_prev_history(key, arg: 1)
1766
- substr = current_line.byteslice(0, @byte_pointer)
1744
+ substr = prev_action_state_value(:search_history) == :empty ? '' : current_line.byteslice(0, @byte_pointer)
1767
1745
  return if @history_pointer == 0
1768
1746
  return if @history_pointer.nil? && substr.empty? && !current_line.empty?
1769
1747
 
1770
1748
  history_range = 0...(@history_pointer || Reline::HISTORY.size)
1771
1749
  h_pointer, line_index = search_history(substr, history_range.reverse_each)
1772
1750
  return unless h_pointer
1773
- move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
1751
+ move_history(h_pointer, line: line_index || :start, cursor: substr.empty? ? :end : @byte_pointer)
1774
1752
  arg -= 1
1753
+ set_next_action_state(:search_history, :empty) if substr.empty?
1775
1754
  ed_search_prev_history(key, arg: arg) if arg > 0
1776
1755
  end
1777
1756
  alias_method :history_search_backward, :ed_search_prev_history
1778
1757
 
1779
1758
  private def ed_search_next_history(key, arg: 1)
1780
- substr = current_line.byteslice(0, @byte_pointer)
1759
+ substr = prev_action_state_value(:search_history) == :empty ? '' : current_line.byteslice(0, @byte_pointer)
1781
1760
  return if @history_pointer.nil?
1782
1761
 
1783
1762
  history_range = @history_pointer + 1...Reline::HISTORY.size
1784
1763
  h_pointer, line_index = search_history(substr, history_range)
1785
1764
  return if h_pointer.nil? and not substr.empty?
1786
1765
 
1787
- move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
1766
+ move_history(h_pointer, line: line_index || :start, cursor: substr.empty? ? :end : @byte_pointer)
1788
1767
  arg -= 1
1768
+ set_next_action_state(:search_history, :empty) if substr.empty?
1789
1769
  ed_search_next_history(key, arg: arg) if arg > 0
1790
1770
  end
1791
1771
  alias_method :history_search_forward, :ed_search_next_history
@@ -1941,7 +1921,7 @@ class Reline::LineEditor
1941
1921
  alias_method :kill_whole_line, :em_kill_line
1942
1922
 
1943
1923
  private def em_delete(key)
1944
- if current_line.empty? and @buffer_of_lines.size == 1 and key == "\C-d".ord
1924
+ if buffer_empty? and key == "\C-d".ord
1945
1925
  @eof = true
1946
1926
  finish
1947
1927
  elsif @byte_pointer < current_line.bytesize
@@ -1986,9 +1966,8 @@ class Reline::LineEditor
1986
1966
  private def ed_clear_screen(key)
1987
1967
  Reline::IOGate.clear_screen
1988
1968
  @screen_size = Reline::IOGate.get_screen_size
1989
- @rendered_screen.lines = []
1990
1969
  @rendered_screen.base_y = 0
1991
- @rendered_screen.cursor_y = 0
1970
+ clear_rendered_screen_cache
1992
1971
  end
1993
1972
  alias_method :clear_screen, :ed_clear_screen
1994
1973
 
@@ -2263,9 +2242,11 @@ class Reline::LineEditor
2263
2242
  line, cut = byteslice!(current_line, @byte_pointer, byte_pointer_diff)
2264
2243
  elsif byte_pointer_diff < 0
2265
2244
  line, cut = byteslice!(current_line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
2245
+ else
2246
+ return
2266
2247
  end
2267
2248
  copy_for_vi(cut)
2268
- set_current_line(line || '', @byte_pointer + (byte_pointer_diff < 0 ? byte_pointer_diff : 0))
2249
+ set_current_line(line, @byte_pointer + (byte_pointer_diff < 0 ? byte_pointer_diff : 0))
2269
2250
  end
2270
2251
 
2271
2252
  private def vi_yank(key, arg: nil)
@@ -2284,13 +2265,14 @@ class Reline::LineEditor
2284
2265
  cut = current_line.byteslice(@byte_pointer, byte_pointer_diff)
2285
2266
  elsif byte_pointer_diff < 0
2286
2267
  cut = current_line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff)
2268
+ else
2269
+ return
2287
2270
  end
2288
2271
  copy_for_vi(cut)
2289
2272
  end
2290
2273
 
2291
2274
  private def vi_list_or_eof(key)
2292
- if current_line.empty? and @buffer_of_lines.size == 1
2293
- set_current_line('', 0)
2275
+ if buffer_empty?
2294
2276
  @eof = true
2295
2277
  finish
2296
2278
  else
@@ -2551,4 +2533,16 @@ class Reline::LineEditor
2551
2533
  target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
2552
2534
  set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
2553
2535
  end
2536
+
2537
+ private def prev_action_state_value(type)
2538
+ @prev_action_state[0] == type ? @prev_action_state[1] : nil
2539
+ end
2540
+
2541
+ private def set_next_action_state(type, value)
2542
+ @next_action_state = [type, value]
2543
+ end
2544
+
2545
+ private def re_read_init_file(_key)
2546
+ @config.reload
2547
+ end
2554
2548
  end
@@ -1,4 +1,7 @@
1
1
  begin
2
+ # Ignore warning `Add fiddle to your Gemfile or gemspec` in Ruby 3.4.
3
+ # terminfo.rb and ansi.rb supports fiddle unavailable environment.
4
+ verbose, $VERBOSE = $VERBOSE, nil
2
5
  require 'fiddle'
3
6
  require 'fiddle/import'
4
7
  rescue LoadError
@@ -7,6 +10,8 @@ rescue LoadError
7
10
  false
8
11
  end
9
12
  end
13
+ ensure
14
+ $VERBOSE = verbose
10
15
  end
11
16
 
12
17
  module Reline::Terminfo
@@ -78,7 +83,7 @@ module Reline::Terminfo
78
83
  end
79
84
 
80
85
  def self.setupterm(term, fildes)
81
- errret_int = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT)
86
+ errret_int = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT, Fiddle::RUBY_FREE)
82
87
  ret = @setupterm.(term, fildes, errret_int)
83
88
  case ret
84
89
  when 0 # OK