reline 0.2.8.pre.2 → 0.2.8.pre.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45220c00c821168746654f6c7f5ad3cc88ff8b4e3d3b6e5aefccc83b34392041
4
- data.tar.gz: a3bbf71304ce777dbae4d5b1cc91f5a2b297b811194947e5e8e8a27b229667a2
3
+ metadata.gz: 161818586702ae2834bf5e6490adf5dcec415256925ffd83339ffe6ef3c13012
4
+ data.tar.gz: 3ab65900ed4022e1baa2213d560938339711264e3188597c4eb98bc1891c81a8
5
5
  SHA512:
6
- metadata.gz: a9d8e4a15c1eff337dc476b8b4f2d603b64d35faf255a9984f119b2f14a76bcd93f145d01d1e0698e2cb0a3d80c28c8b3baa343866e3cb7b8b28ab4642e77ebf
7
- data.tar.gz: fcc70f912f7472acb0d7eeee8f221a60d06e3f08cd079b37a988392eca35723753e3b02638a4bcbb41876dc59cfcb46349b16bfff88e336ecea9bd2a4cf93231
6
+ metadata.gz: 610c5367d68b627fb7e0a7bef7919d147b5a19539725f9a2d184bbed69b0988c613acf1f001d2f05857fce2490e7309e666a4327f1f15cd0541e3bb7db5089ec
7
+ data.tar.gz: b567f8283fe5637161e21536f500f6824d9a92aadf940e10386d27cf4df29940d3e3d6cb95a7a4fff6e711ac33c73f870ee419b45d44274184160b37354d9d77
@@ -24,6 +24,7 @@ class Reline::GeneralIO
24
24
  end
25
25
 
26
26
  @@buf = []
27
+ @@input = STDIN
27
28
 
28
29
  def self.input=(val)
29
30
  @@input = val
@@ -499,6 +499,14 @@ class Reline::LineEditor
499
499
  @line_editor.call_completion_proc_with_checking_args(pre, target, post)
500
500
  end
501
501
 
502
+ def set_dialog(dialog)
503
+ @dialog = dialog
504
+ end
505
+
506
+ def dialog
507
+ @dialog
508
+ end
509
+
502
510
  def set_cursor_pos(col, row)
503
511
  @cursor_pos.x = col
504
512
  @cursor_pos.y = row
@@ -530,19 +538,33 @@ class Reline::LineEditor
530
538
  end
531
539
 
532
540
  class Dialog
533
- attr_reader :name
534
- attr_accessor :column, :vertical_offset, :contents, :lines_backup
541
+ attr_reader :name, :contents, :width
542
+ attr_accessor :scroll_top, :column, :vertical_offset, :lines_backup
535
543
 
536
544
  def initialize(name, proc_scope)
537
545
  @name = name
538
546
  @proc_scope = proc_scope
547
+ @width = nil
548
+ @scroll_top = 0
539
549
  end
540
550
 
541
551
  def set_cursor_pos(col, row)
542
552
  @proc_scope.set_cursor_pos(col, row)
543
553
  end
544
554
 
555
+ def width=(v)
556
+ @width = v
557
+ end
558
+
559
+ def contents=(contents)
560
+ @contents = contents
561
+ if contents and @width.nil?
562
+ @width = contents.map{ |line| Reline::Unicode.calculate_width(line, true) }.max
563
+ end
564
+ end
565
+
545
566
  def call
567
+ @proc_scope.set_dialog(self)
546
568
  @proc_scope.call
547
569
  end
548
570
  end
@@ -553,27 +575,24 @@ class Reline::LineEditor
553
575
  end
554
576
 
555
577
  DIALOG_HEIGHT = 20
556
- DIALOG_WIDTH = 40
557
578
  private def render_dialog(cursor_column)
558
579
  @dialogs.each do |dialog|
559
580
  render_each_dialog(dialog, cursor_column)
560
581
  end
561
582
  end
562
583
 
584
+ private def padding_space_with_escape_sequences(str, width)
585
+ str + (' ' * (width - calculate_width(str, true)))
586
+ end
587
+
563
588
  private def render_each_dialog(dialog, cursor_column)
564
589
  if @in_pasting
565
590
  dialog.contents = nil
566
591
  return
567
592
  end
568
593
  dialog.set_cursor_pos(cursor_column, @first_line_started_from + @started_from)
569
- pos, result, pointer, bg = dialog.call
570
- old_dialog_contents = dialog.contents
571
- old_dialog_column = dialog.column
572
- old_dialog_vertical_offset = dialog.vertical_offset
573
- if result and not result.empty?
574
- dialog.contents = result
575
- dialog.contents = dialog.contents[0...DIALOG_HEIGHT] if dialog.contents.size > DIALOG_HEIGHT
576
- else
594
+ dialog_render_info = dialog.call
595
+ if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
577
596
  dialog.lines_backup = {
578
597
  lines: modify_lines(whole_lines),
579
598
  line_index: @line_index,
@@ -585,39 +604,59 @@ class Reline::LineEditor
585
604
  dialog.contents = nil
586
605
  return
587
606
  end
607
+ old_dialog = dialog.clone
608
+ dialog.width = dialog_render_info.width if dialog_render_info.width
609
+ height = dialog_render_info.height || DIALOG_HEIGHT
610
+ pointer = dialog_render_info.pointer
611
+ dialog.contents = dialog_render_info.contents
612
+ height = dialog.contents.size if dialog.contents.size < height
613
+ if dialog.contents.size > height
614
+ if dialog_render_info.pointer
615
+ if dialog_render_info.pointer < 0
616
+ dialog.scroll_top = 0
617
+ elsif (dialog_render_info.pointer - dialog.scroll_top) >= (height - 1)
618
+ dialog.scroll_top = dialog_render_info.pointer - (height - 1)
619
+ elsif (dialog_render_info.pointer - dialog.scroll_top) < 0
620
+ dialog.scroll_top = dialog_render_info.pointer
621
+ end
622
+ pointer = dialog_render_info.pointer - dialog.scroll_top
623
+ end
624
+ dialog.contents = dialog.contents[dialog.scroll_top, height]
625
+ end
588
626
  upper_space = @first_line_started_from - @started_from
589
627
  lower_space = @highest_in_all - @first_line_started_from - @started_from - 1
590
- dialog.column = pos.x
591
- diff = (dialog.column + DIALOG_WIDTH) - (@screen_size.last - 1)
628
+ dialog.column = dialog_render_info.pos.x
629
+ diff = (dialog.column + dialog.width) - (@screen_size.last - 1)
592
630
  if diff > 0
593
631
  dialog.column -= diff
594
632
  end
595
- if (lower_space + @rest_height) >= DIALOG_HEIGHT
596
- dialog.vertical_offset = pos.y + 1
597
- elsif upper_space >= DIALOG_HEIGHT
598
- dialog.vertical_offset = pos.y + -(DIALOG_HEIGHT + 1)
633
+ if (lower_space + @rest_height - dialog_render_info.pos.y) >= height
634
+ dialog.vertical_offset = dialog_render_info.pos.y + 1
635
+ elsif upper_space >= height
636
+ dialog.vertical_offset = dialog_render_info.pos.y - height
599
637
  else
600
- if (lower_space + @rest_height) < DIALOG_HEIGHT
601
- scroll_down(DIALOG_HEIGHT)
602
- move_cursor_up(DIALOG_HEIGHT)
638
+ if (lower_space + @rest_height - dialog_render_info.pos.y) < height
639
+ scroll_down(height + dialog_render_info.pos.y)
640
+ move_cursor_up(height + dialog_render_info.pos.y)
603
641
  end
604
- dialog.vertical_offset = pos.y + 1
642
+ dialog.vertical_offset = dialog_render_info.pos.y + 1
605
643
  end
606
644
  Reline::IOGate.hide_cursor
607
- reset_dialog(dialog, old_dialog_contents, old_dialog_column, old_dialog_vertical_offset)
645
+ reset_dialog(dialog, old_dialog)
608
646
  move_cursor_down(dialog.vertical_offset)
609
647
  Reline::IOGate.move_cursor_column(dialog.column)
610
648
  dialog.contents.each_with_index do |item, i|
611
649
  if i == pointer
612
650
  bg_color = '45'
613
651
  else
614
- if bg
615
- bg_color = bg
652
+ if dialog_render_info.bg_color
653
+ bg_color = dialog_render_info.bg_color
616
654
  else
617
655
  bg_color = '46'
618
656
  end
619
657
  end
620
- @output.write "\e[#{bg_color}m%-#{DIALOG_WIDTH}s\e[49m" % item.slice(0, DIALOG_WIDTH)
658
+ str = padding_space_with_escape_sequences(Reline::Unicode.take_range(item, 0, dialog.width), dialog.width)
659
+ @output.write "\e[#{bg_color}m#{str}\e[49m"
621
660
  Reline::IOGate.move_cursor_column(dialog.column)
622
661
  move_cursor_down(1) if i < (dialog.contents.size - 1)
623
662
  end
@@ -633,8 +672,8 @@ class Reline::LineEditor
633
672
  }
634
673
  end
635
674
 
636
- private def reset_dialog(dialog, old_dialog_contents, old_dialog_column, old_dialog_vertical_offset)
637
- return if dialog.lines_backup.nil? or old_dialog_contents.nil?
675
+ private def reset_dialog(dialog, old_dialog)
676
+ return if dialog.lines_backup.nil? or old_dialog.contents.nil?
638
677
  prompt, prompt_width, prompt_list = check_multiline_prompt(dialog.lines_backup[:lines], prompt)
639
678
  visual_lines = []
640
679
  visual_start = nil
@@ -650,76 +689,80 @@ class Reline::LineEditor
650
689
  old_y = dialog.lines_backup[:first_line_started_from] + dialog.lines_backup[:started_from]
651
690
  y = @first_line_started_from + @started_from
652
691
  y_diff = y - old_y
653
- if (old_y + old_dialog_vertical_offset) < (y + dialog.vertical_offset)
692
+ if (old_y + old_dialog.vertical_offset) < (y + dialog.vertical_offset)
654
693
  # rerender top
655
- move_cursor_down(old_dialog_vertical_offset - y_diff)
656
- start = visual_start + old_dialog_vertical_offset
657
- line_num = dialog.vertical_offset - old_dialog_vertical_offset
694
+ move_cursor_down(old_dialog.vertical_offset - y_diff)
695
+ start = visual_start + old_dialog.vertical_offset
696
+ line_num = dialog.vertical_offset - old_dialog.vertical_offset
658
697
  line_num.times do |i|
659
- Reline::IOGate.move_cursor_column(old_dialog_column)
698
+ Reline::IOGate.move_cursor_column(old_dialog.column)
660
699
  if visual_lines[start + i].nil?
661
- s = ' ' * DIALOG_WIDTH
700
+ s = ' ' * dialog.width
662
701
  else
663
- s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog_column, DIALOG_WIDTH)
702
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, dialog.width)
703
+ s = padding_space_with_escape_sequences(s, dialog.width)
664
704
  end
665
- @output.write "\e[39m\e[49m%-#{DIALOG_WIDTH}s\e[39m\e[49m" % s
705
+ @output.write "\e[39m\e[49m#{s}\e[39m\e[49m"
666
706
  move_cursor_down(1) if i < (line_num - 1)
667
707
  end
668
- move_cursor_up(old_dialog_vertical_offset + line_num - 1 - y_diff)
708
+ move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
669
709
  end
670
- if (old_y + old_dialog_vertical_offset + old_dialog_contents.size) > (y + dialog.vertical_offset + dialog.contents.size)
710
+ if (old_y + old_dialog.vertical_offset + old_dialog.contents.size) > (y + dialog.vertical_offset + dialog.contents.size)
671
711
  # rerender bottom
672
712
  move_cursor_down(dialog.vertical_offset + dialog.contents.size - y_diff)
673
713
  start = visual_start + dialog.vertical_offset + dialog.contents.size
674
- line_num = (old_dialog_vertical_offset + old_dialog_contents.size) - (dialog.vertical_offset + dialog.contents.size)
714
+ line_num = (old_dialog.vertical_offset + old_dialog.contents.size) - (dialog.vertical_offset + dialog.contents.size)
675
715
  line_num.times do |i|
676
- Reline::IOGate.move_cursor_column(old_dialog_column)
716
+ Reline::IOGate.move_cursor_column(old_dialog.column)
677
717
  if visual_lines[start + i].nil?
678
- s = ' ' * DIALOG_WIDTH
718
+ s = ' ' * dialog.width
679
719
  else
680
- s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog_column, DIALOG_WIDTH)
720
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, dialog.width)
721
+ s = padding_space_with_escape_sequences(s, dialog.width)
681
722
  end
682
- @output.write "\e[39m\e[49m%-#{DIALOG_WIDTH}s\e[39m\e[49m" % s
723
+ @output.write "\e[39m\e[49m#{s}\e[39m\e[49m"
683
724
  move_cursor_down(1) if i < (line_num - 1)
684
725
  end
685
726
  move_cursor_up(dialog.vertical_offset + dialog.contents.size + line_num - 1 - y_diff)
686
727
  end
687
- if old_dialog_column < dialog.column
728
+ if old_dialog.column < dialog.column
688
729
  # rerender left
689
- move_cursor_down(old_dialog_vertical_offset - y_diff)
690
- width = dialog.column - old_dialog_column
691
- start = visual_start + old_dialog_vertical_offset
692
- line_num = old_dialog_contents.size
730
+ move_cursor_down(old_dialog.vertical_offset - y_diff)
731
+ width = dialog.column - old_dialog.column
732
+ start = visual_start + old_dialog.vertical_offset
733
+ line_num = old_dialog.contents.size
693
734
  line_num.times do |i|
694
- Reline::IOGate.move_cursor_column(old_dialog_column)
735
+ Reline::IOGate.move_cursor_column(old_dialog.column)
695
736
  if visual_lines[start + i].nil?
696
737
  s = ' ' * width
697
738
  else
698
- s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog_column, width)
739
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column, width)
740
+ s = padding_space_with_escape_sequences(s, dialog.width)
699
741
  end
700
- @output.write "\e[39m\e[49m%-#{width}s\e[39m\e[49m" % s
742
+ @output.write "\e[39m\e[49m#{s}\e[39m\e[49m"
701
743
  move_cursor_down(1) if i < (line_num - 1)
702
744
  end
703
- move_cursor_up(old_dialog_vertical_offset + line_num - 1 - y_diff)
745
+ move_cursor_up(old_dialog.vertical_offset + line_num - 1 - y_diff)
704
746
  end
705
- if (old_dialog_column + DIALOG_WIDTH) > (dialog.column + DIALOG_WIDTH)
747
+ if (old_dialog.column + old_dialog.width) > (dialog.column + dialog.width)
706
748
  # rerender right
707
- move_cursor_down(old_dialog_vertical_offset + y_diff)
708
- width = (old_dialog_column + DIALOG_WIDTH) - (dialog.column + DIALOG_WIDTH)
709
- start = visual_start + old_dialog_vertical_offset
710
- line_num = old_dialog_contents.size
749
+ move_cursor_down(old_dialog.vertical_offset + y_diff)
750
+ width = (old_dialog.column + old_dialog.width) - (dialog.column + dialog.width)
751
+ start = visual_start + old_dialog.vertical_offset
752
+ line_num = old_dialog.contents.size
711
753
  line_num.times do |i|
712
- Reline::IOGate.move_cursor_column(old_dialog_column + DIALOG_WIDTH)
754
+ Reline::IOGate.move_cursor_column(old_dialog.column + dialog.width)
713
755
  if visual_lines[start + i].nil?
714
756
  s = ' ' * width
715
757
  else
716
- s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog_column + DIALOG_WIDTH, width)
758
+ s = Reline::Unicode.take_range(visual_lines[start + i], old_dialog.column + dialog.width, width)
759
+ s = padding_space_with_escape_sequences(s, dialog.width)
717
760
  end
718
- Reline::IOGate.move_cursor_column(dialog.column + DIALOG_WIDTH)
719
- @output.write "\e[39m\e[49m%-#{width}s\e[39m\e[49m" % s
761
+ Reline::IOGate.move_cursor_column(dialog.column + dialog.width)
762
+ @output.write "\e[39m\e[49m#{s}\e[39m\e[49m"
720
763
  move_cursor_down(1) if i < (line_num - 1)
721
764
  end
722
- move_cursor_up(old_dialog_vertical_offset + line_num - 1 + y_diff)
765
+ move_cursor_up(old_dialog.vertical_offset + line_num - 1 + y_diff)
723
766
  end
724
767
  Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
725
768
  end
@@ -752,13 +795,14 @@ class Reline::LineEditor
752
795
  dialog_vertical_size = dialog.contents.size
753
796
  dialog_vertical_size.times do |i|
754
797
  if i < visual_lines_under_dialog.size
755
- Reline::IOGate.move_cursor_column(0)
756
- @output.write "\e[39m\e[49m%-#{DIALOG_WIDTH}s\e[39m\e[49m" % visual_lines_under_dialog[i]
798
+ Reline::IOGate.move_cursor_column(dialog.column)
799
+ str = Reline::Unicode.take_range(visual_lines_under_dialog[i], dialog.column, dialog.width)
800
+ str = padding_space_with_escape_sequences(str, dialog.width)
801
+ @output.write "\e[39m\e[49m#{str}\e[39m\e[49m"
757
802
  else
758
803
  Reline::IOGate.move_cursor_column(dialog.column)
759
- @output.write "\e[39m\e[49m#{' ' * DIALOG_WIDTH}\e[39m\e[49m"
804
+ @output.write "\e[39m\e[49m#{' ' * dialog.width}\e[39m\e[49m"
760
805
  end
761
- Reline::IOGate.erase_after_cursor
762
806
  move_cursor_down(1) if i < (dialog_vertical_size - 1)
763
807
  end
764
808
  move_cursor_up(dialog_vertical_size - 1 + dialog.vertical_offset)
@@ -1252,8 +1296,10 @@ class Reline::LineEditor
1252
1296
  end
1253
1297
  end
1254
1298
  completed = @completion_journey_data.list[@completion_journey_data.pointer]
1255
- @line = @completion_journey_data.preposing + completed + @completion_journey_data.postposing
1256
- line_to_pointer = @completion_journey_data.preposing + completed
1299
+ new_line = (@completion_journey_data.preposing + completed + @completion_journey_data.postposing).split("\n")[@line_index]
1300
+ @line = new_line.nil? ? String.new(encoding: @encoding) : new_line
1301
+ line_to_pointer = (@completion_journey_data.preposing + completed).split("\n").last
1302
+ line_to_pointer = String.new(encoding: @encoding) if line_to_pointer.nil?
1257
1303
  @cursor_max = calculate_width(@line)
1258
1304
  @cursor = calculate_width(line_to_pointer)
1259
1305
  @byte_pointer = line_to_pointer.bytesize
@@ -186,9 +186,9 @@ class Reline::Unicode
186
186
  end
187
187
 
188
188
  # Take a chunk of a String with escape sequences.
189
- def self.take_range(str, col, length, encoding = str.encoding)
189
+ def self.take_range(str, start_col, max_width, encoding = str.encoding)
190
190
  chunk = String.new(encoding: encoding)
191
- width = 0
191
+ total_width = 0
192
192
  rest = str.encode(Encoding::UTF_8)
193
193
  in_zero_width = false
194
194
  rest.scan(WIDTH_SCANNER) do |gc|
@@ -206,9 +206,10 @@ class Reline::Unicode
206
206
  if in_zero_width
207
207
  chunk << gc
208
208
  else
209
- width = get_mbchar_width(gc)
210
- break if (width + length) <= col
211
- chunk << gc if col <= width
209
+ mbchar_width = get_mbchar_width(gc)
210
+ total_width += mbchar_width
211
+ break if (start_col + max_width) < total_width
212
+ chunk << gc if start_col < total_width
212
213
  end
213
214
  end
214
215
  end
@@ -1,3 +1,3 @@
1
1
  module Reline
2
- VERSION = '0.2.8.pre.2'
2
+ VERSION = '0.2.8.pre.6'
3
3
  end
data/lib/reline.rb CHANGED
@@ -18,6 +18,7 @@ module Reline
18
18
 
19
19
  Key = Struct.new('Key', :char, :combined_char, :with_meta)
20
20
  CursorPos = Struct.new(:x, :y)
21
+ DialogRenderInfo = Struct.new(:pos, :contents, :pointer, :bg_color, :width, :height, keyword_init: true)
21
22
 
22
23
  class Core
23
24
  ATTR_READER_NAMES = %i(
@@ -193,7 +194,7 @@ module Reline
193
194
  # Auto complete starts only when edited
194
195
  return nil
195
196
  end
196
- pre, target, post= retrieve_completion_block(true)
197
+ pre, target, post = retrieve_completion_block(true)
197
198
  if target.nil? or target.empty?# or target.size <= 3
198
199
  return nil
199
200
  end
@@ -219,9 +220,9 @@ module Reline
219
220
  cursor_pos_to_render = Reline::CursorPos.new(x, y)
220
221
  if context and context.is_a?(Array)
221
222
  context.clear
222
- context.push(cursor_pos_to_render, result, pointer)
223
+ context.push(cursor_pos_to_render, result, pointer, dialog)
223
224
  end
224
- [cursor_pos_to_render, result, pointer, nil]
225
+ DialogRenderInfo.new(pos: cursor_pos_to_render, contents: result, pointer: pointer, height: 15)
225
226
  }
226
227
  Reline::DEFAULT_DIALOG_CONTEXT = Array.new
227
228
 
@@ -483,6 +484,7 @@ module Reline
483
484
  def_single_delegators :core, :last_incremental_search
484
485
  def_single_delegators :core, :last_incremental_search=
485
486
  def_single_delegators :core, :add_dialog_proc
487
+ def_single_delegators :core, :autocompletion, :autocompletion=
486
488
 
487
489
  def_single_delegators :core, :readmultiline
488
490
  def_instance_delegators self, :readmultiline
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.2.8.pre.2
4
+ version: 0.2.8.pre.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - aycabta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-29 00:00:00.000000000 Z
11
+ date: 2021-09-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console