diff options
author | aycabta <aycabta@gmail.com> | 2019-05-13 00:22:27 +0900 |
---|---|---|
committer | aycabta <aycabta@gmail.com> | 2019-05-13 00:22:27 +0900 |
commit | 0f45bd0584f1550e153babc339ad7671e2424d20 (patch) | |
tree | ecabfd107eb49b00b3a2139762d4f44da958f354 /lib | |
parent | 11476e9902405b90b7493fed43f9fc2e6db9a32c (diff) | |
download | ruby-0f45bd0584f1550e153babc339ad7671e2424d20.tar.gz |
Split namespace of env-dependent I/O classes
Diffstat (limited to 'lib')
-rw-r--r-- | lib/reline.rb | 35 | ||||
-rw-r--r-- | lib/reline/ansi.rb | 16 | ||||
-rw-r--r-- | lib/reline/general_io.rb | 55 | ||||
-rw-r--r-- | lib/reline/line_editor.rb | 65 | ||||
-rw-r--r-- | lib/reline/windows.rb | 12 |
5 files changed, 125 insertions, 58 deletions
diff --git a/lib/reline.rb b/lib/reline.rb index 42dbd3e8e9..447551fe2f 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -82,12 +82,6 @@ module Reline raise NotImplementedError end - if IS_WINDOWS - require 'reline/windows' - else - require 'reline/ansi' - end - def retrieve_completion_block(line, byte_pointer) break_regexp = /[#{Regexp.escape(@@basic_word_break_characters)}]/ before_pointer = line.byteslice(0, byte_pointer) @@ -132,10 +126,11 @@ module Reline end def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination) - otio = prep @@config.read + otio = Reline::IO.prep may_req_ambiguous_char_width + @@line_editor.reset(prompt) if multiline @@line_editor.multiline_on if block_given? @@ -171,7 +166,7 @@ module Reline key_stroke = Reline::KeyStroke.new(config) begin - while c = getc + while c = Reline::IO.getc key_stroke.input_to!(c)&.then { |inputs| inputs.each { |c| @@line_editor.input_key(c) @@ -180,25 +175,35 @@ module Reline } break if @@line_editor.finished? end - Reline.move_cursor_column(0) + Reline::IO.move_cursor_column(0) rescue StandardError => e - deprep(otio) + Reline::IO.deprep(otio) raise e end - deprep(otio) + Reline::IO.deprep(otio) end def may_req_ambiguous_char_width + @@ambiguous_width = 2 if Reline::IO == Reline::GeneralIO or STDOUT.is_a?(File) return if @@ambiguous_width - Reline.move_cursor_column(0) + Reline::IO.move_cursor_column(0) print "\u{25bd}" - @@ambiguous_width = Reline.cursor_pos.x - Reline.move_cursor_column(0) - Reline.erase_after_cursor + @@ambiguous_width = Reline::IO.cursor_pos.x + Reline::IO.move_cursor_column(0) + Reline::IO.erase_after_cursor end def self.ambiguous_width @@ambiguous_width end end + +if Reline::IS_WINDOWS + require 'reline/windows' + Reline::IO = Reline::Windows +else + require 'reline/ansi' + Reline::IO = Reline::ANSI +end +require 'reline/general_io' diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb index f34c4207e5..eb13c7f55b 100644 --- a/lib/reline/ansi.rb +++ b/lib/reline/ansi.rb @@ -1,13 +1,13 @@ -module Reline - def getc +class Reline::ANSI + def self.getc c = nil - until c - return nil if @line_editor.finished? + loop do result = select([$stdin], [], [], 0.1) next if result.nil? c = $stdin.read(1) + break end - c.ord + c&.ord end def self.get_screen_size @@ -29,7 +29,7 @@ module Reline end end m = res.match(/(?<row>\d+);(?<column>\d+)/) - CursorPos.new(m[:column].to_i - 1, m[:row].to_i - 1) + Reline::CursorPos.new(m[:column].to_i - 1, m[:row].to_i - 1) end def self.move_cursor_column(x) @@ -66,7 +66,7 @@ module Reline print "\e[1;1H" end - def prep + def self.prep int_handle = Signal.trap('INT', 'IGNORE') otio = `stty -g`.chomp setting = ' -echo -icrnl cbreak' @@ -79,7 +79,7 @@ module Reline otio end - def deprep(otio) + def self.deprep(otio) int_handle = Signal.trap('INT', 'IGNORE') `stty #{otio}` Signal.trap('INT', int_handle) diff --git a/lib/reline/general_io.rb b/lib/reline/general_io.rb new file mode 100644 index 0000000000..0ea31b972b --- /dev/null +++ b/lib/reline/general_io.rb @@ -0,0 +1,55 @@ +require 'timeout' + +class Reline::GeneralIO + @@buf = [] + + def self.input=(val) + @@input = val + end + + def self.getc + c = nil + loop do + result = select([@@input], [], [], 0.1) + next if result.nil? + c = @@input.read(1) + break + end + c&.ord + end + + def self.get_screen_size + [1, 1] + end + + def self.cursor_pos + Reline::CursorPos.new(1, 1) + end + + def self.move_cursor_column(val) + end + + def self.move_cursor_up(val) + end + + def self.move_cursor_down(val) + end + + def self.erase_after_cursor + end + + def self.scroll_down(val) + end + + def self.clear_screen + end + + def self.set_screen_size(rows, columns) + end + + def self.prep + end + + def self.deprep(otio) + end +end diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index 144dd73679..1b20fafdb4 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -76,41 +76,48 @@ class Reline::LineEditor CompletionJourneyData = Struct.new('CompletionJourneyData', :preposing, :postposing, :list, :pointer) MenuInfo = Struct.new('MenuInfo', :target, :list) - def initialize(config, prompt = '', encoding = Encoding.default_external) + def initialize(config) @config = config + reset + end + + def reset(prompt = '', encoding = Encoding.default_external) @prompt = prompt - @prompt_width = calculate_width(@prompt) - @cursor = 0 - @cursor_max = 0 - @byte_pointer = 0 @encoding = encoding - @buffer_of_lines = [String.new(encoding: @encoding)] - @line_index = 0 - @previous_line_index = nil - @line = @buffer_of_lines[0] + @prompt_width = calculate_width(@prompt) @is_multiline = false @finished = false @cleared = false @rerender_all = false @is_confirm_multiline_termination = false @history_pointer = nil - @line_backup_in_history = nil @kill_ring = Reline::KillRing.new @vi_clipboard = '' @vi_arg = nil - @multibyte_buffer = String.new(encoding: 'ASCII-8BIT') @meta_prefix = false @waiting_proc = nil @waiting_operator_proc = nil @completion_journey_data = nil @completion_state = CompletionState::NORMAL @perfect_matched = nil + @menu_info = nil + @first_prompt = true + @searching_prompt = nil + @first_char = true + @cursor = 0 + @cursor_max = 0 + @byte_pointer = 0 + @buffer_of_lines = [String.new(encoding: @encoding)] + @line_index = 0 + @previous_line_index = nil + @line = @buffer_of_lines[0] @first_line_started_from = 0 @move_up = 0 @started_from = 0 @highest_in_this = 1 @highest_in_all = 1 - @menu_info = nil + @line_backup_in_history = nil + @multibyte_buffer = String.new(encoding: 'ASCII-8BIT') end def multiline_on @@ -158,18 +165,18 @@ class Reline::LineEditor private def scroll_down(val) if val <= @rest_height - Reline.move_cursor_down(val) + Reline::IO.move_cursor_down(val) @rest_height -= val else - Reline.move_cursor_down(@rest_height) - Reline.scroll_down(val - @rest_height) + Reline::IO.move_cursor_down(@rest_height) + Reline::IO.scroll_down(val - @rest_height) @rest_height = 0 end end private def move_cursor_up(val) if val > 0 - Reline.move_cursor_up(val) + Reline::IO.move_cursor_up(val) @rest_height += val elsif val < 0 move_cursor_down(-val) @@ -178,7 +185,7 @@ class Reline::LineEditor private def move_cursor_down(val) if val > 0 - Reline.move_cursor_down(val) + Reline::IO.move_cursor_down(val) @rest_height -= val @rest_height = 0 if @rest_height < 0 elsif val < 0 @@ -210,8 +217,8 @@ class Reline::LineEditor end def rerender # TODO: support physical and logical lines - @rest_height ||= (Reline.get_screen_size.first - 1) - Reline.cursor_pos.y - @screen_size ||= Reline.get_screen_size + @rest_height ||= (Reline::IO.get_screen_size.first - 1) - Reline::IO.cursor_pos.y + @screen_size ||= Reline::IO.get_screen_size if @menu_info puts @menu_info.list.each do |item| @@ -228,7 +235,7 @@ class Reline::LineEditor prompt_width = @prompt_width end if @cleared - Reline.clear_screen + Reline::IO.clear_screen @cleared = false back = 0 @buffer_of_lines.each_with_index do |line, index| @@ -241,7 +248,7 @@ class Reline::LineEditor end move_cursor_up(back) move_cursor_down(@first_line_started_from + @started_from) - Reline.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + Reline::IO.move_cursor_column((prompt_width + @cursor) % @screen_size.last) return end # FIXME: end of logical line sometimes breaks @@ -285,7 +292,7 @@ class Reline::LineEditor @previous_line_index = nil elsif @rerender_all move_cursor_up(@first_line_started_from + @started_from) - Reline.move_cursor_column(0) + Reline::IO.move_cursor_column(0) back = 0 @buffer_of_lines.each do |line| width = prompt_width + calculate_width(line) @@ -297,10 +304,10 @@ class Reline::LineEditor move_cursor_up(back) elsif back < @highest_in_all scroll_down(back) - Reline.erase_after_cursor + Reline::IO.erase_after_cursor (@highest_in_all - back).times do scroll_down(1) - Reline.erase_after_cursor + Reline::IO.erase_after_cursor end move_cursor_up(@highest_in_all) end @@ -327,8 +334,8 @@ class Reline::LineEditor render_partial(prompt, prompt_width, @line) if !@is_multiline or !finished? if @is_multiline and finished? scroll_down(1) unless @buffer_of_lines.last.empty? - Reline.move_cursor_column(0) - Reline.erase_after_cursor + Reline::IO.move_cursor_column(0) + Reline::IO.erase_after_cursor end end @@ -347,9 +354,9 @@ class Reline::LineEditor @started_from = calculate_height_by_width(prompt_width + @cursor) - 1 end visual_lines.each_with_index do |line, index| - Reline.move_cursor_column(0) + Reline::IO.move_cursor_column(0) escaped_print line - Reline.erase_after_cursor + Reline::IO.erase_after_cursor move_cursor_down(1) if index < (visual_lines.size - 1) end if with_control @@ -357,7 +364,7 @@ class Reline::LineEditor puts else move_cursor_up((visual_lines.size - 1) - @started_from) - Reline.move_cursor_column((prompt_width + @cursor) % @screen_size.last) + Reline::IO.move_cursor_column((prompt_width + @cursor) % @screen_size.last) end end visual_lines.size diff --git a/lib/reline/windows.rb b/lib/reline/windows.rb index f65c527ccd..2e7ed89ff9 100644 --- a/lib/reline/windows.rb +++ b/lib/reline/windows.rb @@ -1,6 +1,6 @@ require 'fiddle/import' -module Reline +class Reline::Windows class Win32API DLL = {} TYPEMAP = {"0" => Fiddle::TYPE_VOID, "S" => Fiddle::TYPE_VOIDP, "I" => Fiddle::TYPE_LONG} @@ -52,7 +52,7 @@ module Reline @@hConsoleHandle = @@GetStdHandle.call(STD_OUTPUT_HANDLE) @@buf = [] - def getwch + def self.getwch while @@kbhit.call == 0 sleep(0.001) end @@ -69,7 +69,7 @@ module Reline result end - def getc + def self.getc unless @@buf.empty? return @@buf.shift end @@ -112,7 +112,7 @@ module Reline @@GetConsoleScreenBufferInfo.call(@@hConsoleHandle, csbi) x = csbi[4, 2].unpack('s*').first y = csbi[6, 4].unpack('s*').first - CursorPos.new(x, y) + Reline::CursorPos.new(x, y) end def self.move_cursor_column(val) @@ -161,12 +161,12 @@ module Reline raise NotImplementedError end - def prep + def self.prep # do nothing nil end - def deprep(otio) + def self.deprep(otio) # do nothing end end |