[前][次][番号順一覧][スレッド一覧]

ruby-changes:64241

From: aycabta <ko1@a...>
Date: Thu, 17 Dec 2020 20:24:48 +0900 (JST)
Subject: [ruby-changes:64241] 2b8fa78176 (master): [ruby/reline] Support longer than screen height

https://git.ruby-lang.org/ruby.git/commit/?id=2b8fa78176

From 2b8fa7817643a9ac7632b66ffed7cb5fd3753966 Mon Sep 17 00:00:00 2001
From: aycabta <aycabta@g...>
Date: Sun, 13 Dec 2020 11:30:05 +0900
Subject: [ruby/reline] Support longer than screen height

https://github.com/ruby/reline/commit/e83a3de9ed

diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
index 65878fe..b80a184 100644
--- a/lib/reline/line_editor.rb
+++ b/lib/reline/line_editor.rb
@@ -123,6 +123,7 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L123
   def reset(prompt = '', encoding:)
     @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
     @screen_size = Reline::IOGate.get_screen_size
+    @screen_height = @screen_size.first
     reset_variables(prompt, encoding: encoding)
     @old_trap = Signal.trap('SIGINT') {
       @old_trap.call if @old_trap.respond_to?(:call) # can also be string, ex: "DEFAULT"
@@ -132,6 +133,7 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L133
       @rest_height = (Reline::IOGate.get_screen_size.first - 1) - Reline::IOGate.cursor_pos.y
       old_screen_size = @screen_size
       @screen_size = Reline::IOGate.get_screen_size
+      @screen_height = @screen_size.first
       if old_screen_size.last < @screen_size.last # columns increase
         @rerender_all = true
         rerender
@@ -202,6 +204,7 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L204
     @prompt_cache_time = nil
     @eof = false
     @continuous_insertion_buffer = String.new(encoding: @encoding)
+    @scroll_partial_screen = nil
     reset_line
   end
 
@@ -287,28 +290,28 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L290
     end
   end
 
-  private def calculate_nearest_cursor
-    @cursor_max = calculate_width(line)
+  private def calculate_nearest_cursor(line_to_calc = @line, cursor = @cursor, started_from = @started_from, byte_pointer = @byte_pointer, update = true)
+    new_cursor_max = calculate_width(line_to_calc)
     new_cursor = 0
     new_byte_pointer = 0
     height = 1
     max_width = @screen_size.last
     if @config.editing_mode_is?(:vi_command)
-      last_byte_size = Reline::Unicode.get_prev_mbchar_size(@line, @line.bytesize)
+      last_byte_size = Reline::Unicode.get_prev_mbchar_size(line_to_calc, line_to_calc.bytesize)
       if last_byte_size > 0
-        last_mbchar = @line.byteslice(@line.bytesize - last_byte_size, last_byte_size)
+        last_mbchar = line_to_calc.byteslice(line_to_calc.bytesize - last_byte_size, last_byte_size)
         last_width = Reline::Unicode.get_mbchar_width(last_mbchar)
-        cursor_max = @cursor_max - last_width
+        end_of_line_cursor = new_cursor_max - last_width
       else
-        cursor_max = @cursor_max
+      end_of_line_cursor = new_cursor_max
       end
     else
-      cursor_max = @cursor_max
+    end_of_line_cursor = new_cursor_max
     end
-    @line.encode(Encoding::UTF_8).grapheme_clusters.each do |gc|
+    line_to_calc.encode(Encoding::UTF_8).grapheme_clusters.each do |gc|
       mbchar_width = Reline::Unicode.get_mbchar_width(gc)
       now = new_cursor + mbchar_width
-      if now > cursor_max or now > @cursor
+      if now > end_of_line_cursor or now > cursor
         break
       end
       new_cursor += mbchar_width
@@ -317,9 +320,15 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L320
       end
       new_byte_pointer += gc.bytesize
     end
-    @started_from = height - 1
-    @cursor = new_cursor
-    @byte_pointer = new_byte_pointer
+    new_started_from = height - 1
+    if update
+      @cursor = new_cursor
+      @cursor_max = new_cursor_max
+      @started_from = new_started_from
+      @byte_pointer = new_byte_pointer
+    else
+      [new_cursor, new_cursor_max, new_started_from, new_byte_pointer]
+    end
   end
 
   def rerender_all
@@ -349,33 +358,37 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L358
     if @add_newline_to_end_of_buffer
       rerender_added_newline
       @add_newline_to_end_of_buffer = false
-    elsif @just_cursor_moving and not @rerender_all
-      just_move_cursor
-      @just_cursor_moving = false
-      return
-    elsif @previous_line_index or new_highest_in_this != @highest_in_this
-      rerender_changed_current_line
-      @previous_line_index = nil
-      rendered = true
-    elsif @rerender_all
-      rerender_all_lines
-      @rerender_all = false
-      rendered = true
+    else
+      if @just_cursor_moving and not @rerender_all
+        rendered = just_move_cursor
+        @just_cursor_moving = false
+        return
+      elsif @previous_line_index or new_highest_in_this != @highest_in_this
+        rerender_changed_current_line
+        @previous_line_index = nil
+        rendered = true
+      elsif @rerender_all
+        rerender_all_lines
+        @rerender_all = false
+        rendered = true
+      else
+      end
     end
     line = modify_lines(whole_lines)[@line_index]
     if @is_multiline
       prompt, prompt_width, prompt_list = check_multiline_prompt(whole_lines, prompt)
       if finished?
         # Always rerender on finish because output_modifier_proc may return a different output.
-        render_partial(prompt, prompt_width, line)
+        render_partial(prompt, prompt_width, line, @first_line_started_from)
         scroll_down(1)
         Reline::IOGate.move_cursor_column(0)
         Reline::IOGate.erase_after_cursor
       elsif not rendered
-        render_partial(prompt, prompt_width, line)
+        render_partial(prompt, prompt_width, line, @first_line_started_from)
       end
+      @buffer_of_lines[@line_index] = @line
     else
-      render_partial(prompt, prompt_width, line)
+      render_partial(prompt, prompt_width, line, 0)
       if finished?
         scroll_down(1)
         Reline::IOGate.move_cursor_column(0)
@@ -384,13 +397,46 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L397
     end
   end
 
+  private def calculate_scroll_partial_screen(highest_in_all, cursor_y)
+    if @screen_height < highest_in_all
+      old_scroll_partial_screen = @scroll_partial_screen
+      if cursor_y == 0
+        @scroll_partial_screen = 0
+      elsif cursor_y == (highest_in_all - 1)
+        @scroll_partial_screen = highest_in_all - @screen_height
+      else
+        if @scroll_partial_screen
+          if cursor_y <= @scroll_partial_screen
+            @scroll_partial_screen = cursor_y
+          elsif (@scroll_partial_screen + @screen_height - 1) < cursor_y
+            @scroll_partial_screen = cursor_y - (@screen_height - 1)
+          end
+        else
+          if cursor_y > (@screen_height - 1)
+            @scroll_partial_screen = cursor_y - (@screen_height - 1)
+          else
+            @scroll_partial_screen = 0
+          end
+        end
+      end
+      if @scroll_partial_screen != old_scroll_partial_screen
+        @rerender_all = true
+      end
+    else
+      if @scroll_partial_screen
+        @rerender_all = true
+      end
+      @scroll_partial_screen = nil
+    end
+  end
+
   private def rerender_added_newline
     scroll_down(1)
     new_lines = whole_lines(index: @previous_line_index, line: @line)
     prompt, prompt_width, = check_multiline_prompt(new_lines, prompt)
     @buffer_of_lines[@previous_line_index] = @line
     @line = @buffer_of_lines[@line_index]
-    render_partial(prompt, prompt_width, @line, false)
+    render_partial(prompt, prompt_width, @line, @first_line_started_from + @started_from + 1, with_control: false)
     @cursor = @cursor_max = calculate_width(@line)
     @byte_pointer = @line.bytesize
     @highest_in_all += @highest_in_this
@@ -409,14 +455,25 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L455
       else
         calculate_height_by_lines(@buffer_of_lines[0..(@line_index - 1)], prompt_list || prompt)
       end
-    @line = @buffer_of_lines[@line_index]
-    move_cursor_down(new_first_line_started_from - @first_line_started_from)
-    @first_line_started_from = new_first_line_started_from
-    calculate_nearest_cursor
-    @started_from = calculate_height_by_width(prompt_width + @cursor) - 1
-    move_cursor_down(@started_from)
-    Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+    first_line_diff = new_first_line_started_from - @first_line_started_from
+    new_cursor, _, new_started_from, _ = calculate_nearest_cursor(@line, @cursor, @started_from, @byte_pointer, false)
+    new_started_from = calculate_height_by_width(prompt_width + new_cursor) - 1
+    calculate_scroll_partial_screen(@highest_in_all, new_first_line_started_from + new_started_from)
     @previous_line_index = nil
+    if @rerender_all
+      @line = @buffer_of_lines[@line_index]
+      rerender_all_lines
+      @rerender_all = false
+      true
+    else
+      @line = @buffer_of_lines[@line_index]
+      @first_line_started_from = new_first_line_started_from
+      @started_from = new_started_from
+      @cursor = new_cursor
+      move_cursor_down(first_line_diff + @started_from)
+      Reline::IOGate.move_cursor_column((prompt_width + @cursor) % @screen_size.last)
+      false
+    end
   end
 
   private def rerender_changed_current_line
@@ -479,35 +536,42 @@ class Reline::LineEditor https://github.com/ruby/ruby/blob/trunk/lib/reline/line_editor.rb#L536
       height = calculate_height_by_width(width)
       back += height
     end
-    if back > @highest_in_all
+    old_highest_in_all = @highest_in_all
+    if @line_index.zero?
+      new_first_line_started_from = 0
+    else
+      new_first_line_started_from = calculate_height_by_lines(new_buffer[0..(@line_index - 1)], prompt_list || prompt)
+    end
+    new_started_from = calculate_height_by_width(pr (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]