summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authoraycabta <aycabta@gmail.com>2019-05-13 00:22:27 +0900
committeraycabta <aycabta@gmail.com>2019-05-13 00:22:27 +0900
commit0f45bd0584f1550e153babc339ad7671e2424d20 (patch)
treeecabfd107eb49b00b3a2139762d4f44da958f354 /lib
parent11476e9902405b90b7493fed43f9fc2e6db9a32c (diff)
Split namespace of env-dependent I/O classes
Diffstat (limited to 'lib')
-rw-r--r--lib/reline.rb35
-rw-r--r--lib/reline/ansi.rb16
-rw-r--r--lib/reline/general_io.rb55
-rw-r--r--lib/reline/line_editor.rb65
-rw-r--r--lib/reline/windows.rb12
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