From 9cb821b02486de87b322089302fec3a63cda7b81 Mon Sep 17 00:00:00 2001 From: aycabta Date: Mon, 13 May 2019 02:14:48 +0900 Subject: Implement Reline.input= and Reline.output= --- lib/reline.rb | 18 ++++++++++++++++-- lib/reline/ansi.rb | 37 +++++++++++++++++++++++++------------ lib/reline/line_editor.rb | 13 +++++++++---- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/lib/reline.rb b/lib/reline.rb index 447551fe2f..f038100130 100644 --- a/lib/reline.rb +++ b/lib/reline.rb @@ -26,8 +26,6 @@ module Reline attr_reader :completion_append_character attr_accessor :completion_case_fold attr_accessor :filename_quote_characters - attr_writer :input - attr_writer :output end @@config = Reline::Config.new @@ -82,6 +80,21 @@ module Reline raise NotImplementedError end + def self.input=(val) + raise TypeError unless val.respond_to?(:getc) or val.nil? + if val.respond_to?(:getc) + Reline::GeneralIO.input = val + remove_const('IO') if const_defined?('IO') + const_set('IO', Reline::GeneralIO) + end + end + + @@output = STDOUT + def self.output=(val) + raise TypeError unless val.respond_to?(:write) or val.nil? + @@output = val + end + def retrieve_completion_block(line, byte_pointer) break_regexp = /[#{Regexp.escape(@@basic_word_break_characters)}]/ before_pointer = line.byteslice(0, byte_pointer) @@ -139,6 +152,7 @@ module Reline else @@line_editor.multiline_off end + @@line_editor.output = @@output @@line_editor.completion_proc = @@completion_proc @@line_editor.dig_perfect_match_proc = @@dig_perfect_match_proc @@line_editor.retrieve_completion_block = method(:retrieve_completion_block) diff --git a/lib/reline/ansi.rb b/lib/reline/ansi.rb index eb13c7f55b..8db21fce4c 100644 --- a/lib/reline/ansi.rb +++ b/lib/reline/ansi.rb @@ -2,34 +2,47 @@ class Reline::ANSI def self.getc c = nil loop do - result = select([$stdin], [], [], 0.1) + result = select([STDIN], [], [], 0.1) next if result.nil? - c = $stdin.read(1) + c = STDIN.read(1) break end c&.ord end def self.get_screen_size - $stdin.winsize + STDIN.winsize + rescue Errno::ENOTTY + [24, 80] end def self.set_screen_size(rows, columns) - $stdin.winsize = [rows, columns] + STDIN.winsize = [rows, columns] + self + rescue Errno::ENOTTY self end def self.cursor_pos - res = '' - $stdin.raw do |stdin| - $stdout << "\e[6n" - $stdout.flush - while (c = stdin.getc) != 'R' - res << c if c + begin + res = '' + STDIN.raw do |stdin| + STDOUT << "\e[6n" + STDOUT.flush + while (c = stdin.getc) != 'R' + res << c if c + end end + res + m = res.match(/(?\d+);(?\d+)/) + column = m[:column].to_i - 1 + row = m[:row].to_i - 1 + rescue Errno::ENOTTY + buf = STDOUT.pread(STDOUT.pos, 0) + row = buf.count("\n") + column = buf.rindex("\n") ? (buf.size - buf.rindex("\n")) - 1 : 0 end - m = res.match(/(?\d+);(?\d+)/) - Reline::CursorPos.new(m[:column].to_i - 1, m[:row].to_i - 1) + Reline::CursorPos.new(column, row) end def self.move_cursor_column(x) diff --git a/lib/reline/line_editor.rb b/lib/reline/line_editor.rb index bb66a2ece7..a1c796e76f 100644 --- a/lib/reline/line_editor.rb +++ b/lib/reline/line_editor.rb @@ -11,6 +11,7 @@ class Reline::LineEditor attr_accessor :completion_proc attr_accessor :dig_perfect_match_proc attr_writer :retrieve_completion_block + attr_writer :output ARGUMENTABLE = %i{ ed_delete_next_char @@ -220,9 +221,9 @@ class Reline::LineEditor @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 + @output.puts @menu_info.list.each do |item| - puts item + @output.puts item end @menu_info = nil end @@ -359,12 +360,16 @@ class Reline::LineEditor visual_lines.each_with_index do |line, index| Reline::IO.move_cursor_column(0) escaped_print line + if @first_prompt + @first_prompt = false + @pre_input_hook&.call + end Reline::IO.erase_after_cursor move_cursor_down(1) if index < (visual_lines.size - 1) end if with_control if finished? - puts + @output.puts else move_cursor_up((visual_lines.size - 1) - @started_from) Reline::IO.move_cursor_column((prompt_width + @cursor) % @screen_size.last) @@ -378,7 +383,7 @@ class Reline::LineEditor end private def escaped_print(str) - print str.chars.map { |gr| + @output.print str.chars.map { |gr| escaped = Reline::Unicode::EscapedPairs[gr.ord] if escaped escaped -- cgit v1.2.3