Permalink
Browse files

Merge pull request #27 from tomdz/jline

Fix for #22 that uses JLine when running in JRuby
  • Loading branch information...
2 parents b11829d + f4b0f77 commit fc255baf7fc4f591d2d3816a6e1f4baee6e17108 @JEG2 committed Nov 29, 2011
Showing with 93 additions and 41 deletions.
  1. +92 −33 lib/highline.rb
  2. +1 −8 lib/highline/system_extensions.rb
View
@@ -179,6 +179,21 @@ def initialize( input = $stdin, output = $stdout,
wrap_at = nil, page_at = nil )
@input = input
@output = output
+ if JRUBY
+ require 'java'
+ java_import 'java.io.OutputStreamWriter'
+ java_import 'java.nio.channels.Channels'
+ java_import 'jline.ConsoleReader'
+ java_import 'jline.Terminal'
+
+ @java_input = Channels.newInputStream($stdin.to_channel)
+ @java_output = OutputStreamWriter.new(Channels.newOutputStream($stdout.to_channel))
+ @java_terminal = Terminal.getTerminal
+ @java_console = ConsoleReader.new(@java_input, @java_output)
+ @java_console.setUseHistory(false)
+ @java_console.setBellEnabled(true)
+ @java_console.setUsePagination(false)
+ end
self.wrap_at = wrap_at
self.page_at = page_at
@@ -758,13 +773,34 @@ def get_line( )
answer
else
- raise EOFError, "The input stream is exhausted." if @@track_eof and
- @input.eof?
+ if JRUBY
+ enable_echo_afterwards = @java_terminal.isEchoEnabled
+ @java_terminal.disableEcho
+ begin
+ raw_answer = @java_console.readLine(nil, nil)
+ ensure
+ @java_terminal.enableEcho if enable_echo_afterwards
+ end
+ else
+ raise EOFError, "The input stream is exhausted." if @@track_eof and
+ @input.eof?
+ raw_answer = @input.gets
+ end
- @question.change_case(@question.remove_whitespace(@input.gets))
+ @question.change_case(@question.remove_whitespace(raw_answer))
end
end
-
+
+ def get_single_character(is_stty)
+ if JRUBY
+ @java_console.readVirtualKey
+ elsif is_stty
+ @input.getbyte
+ else
+ get_character(@input)
+ end
+ end
+
#
# Return a line or character of input, as requested for this question.
# Character input will be returned as a single character String,
@@ -776,18 +812,25 @@ def get_line( )
#
def get_response( )
return @question.first_answer if @question.first_answer?
-
+
+ stty = (CHARACTER_MODE == "stty")
+
if @question.character.nil?
if @question.echo == true and @question.limit.nil?
get_line
else
- raw_no_echo_mode if stty = CHARACTER_MODE == "stty"
-
+ if JRUBY
+ enable_echo_afterwards = @java_terminal.isEchoEnabled
+ @java_terminal.disableEcho
+ elsif stty
+ raw_no_echo_mode
+ end
+
line = ""
backspace_limit = 0
begin
- while character = (stty ? @input.getbyte : get_character(@input))
+ while character = get_single_character(stty)
# honor backspace and delete
if character == 127 or character == 8
line.slice!(-1, 1)
@@ -798,17 +841,16 @@ def get_response( )
end
# looking for carriage return (decimal 13) or
# newline (decimal 10) in raw input
- break if character == 13 or character == 10 or
- (@question.limit and line.size == @question.limit)
+ break if character == 13 or character == 10
if @question.echo != false
- if character == 127 or character == 8
- # only backspace if we have characters on the line to
- # eliminate, otherwise we'll tromp over the prompt
- if backspace_limit >= 0 then
- @output.print("\b#{HighLine.Style(:erase_char).code}")
- else
- # do nothing
- end
+ if character == 127 or character == 8
+ # only backspace if we have characters on the line to
+ # eliminate, otherwise we'll tromp over the prompt
+ if backspace_limit >= 0 then
+ @output.print("\b#{HighLine.Style(:erase_char).code}")
+ else
+ # do nothing
+ end
else
if @question.echo == true
@output.print(character.chr)
@@ -818,35 +860,52 @@ def get_response( )
end
@output.flush
end
+ break if @question.limit and line.size == @question.limit
end
ensure
- restore_mode if stty
+ if JRUBY
+ @java_terminal.enableEcho if enable_echo_afterwards
+ elsif stty
+ restore_mode
+ end
end
if @question.overwrite
@output.print("\r#{HighLine.Style(:erase_line).code}")
@output.flush
else
say("\n")
end
-
+
@question.change_case(@question.remove_whitespace(line))
end
- elsif @question.character == :getc
- @question.change_case(@input.getbyte.chr)
else
- response = get_character(@input).chr
- if @question.overwrite
- @output.print("\r#{HighLine.Style(:erase_line).code}")
- @output.flush
- else
- echo = if @question.echo == true
- response
- elsif @question.echo != false
- @question.echo
+ if JRUBY
+ enable_echo_afterwards = @java_terminal.isEchoEnabled
+ @java_terminal.disableEcho
+ end
+ begin
+ if @question.character == :getc
+ response = get_single_character(true).chr
else
- ""
+ response = get_single_character(stty).chr
+ if @question.overwrite
+ @output.print("\r#{HighLine.Style(:erase_line).code}")
+ @output.flush
+ else
+ echo = if @question.echo == true
+ response
+ elsif @question.echo != false
+ @question.echo
+ else
+ ""
+ end
+ say("#{echo}\n")
+ end
+ end
+ ensure
+ if JRUBY
+ @java_terminal.enableEcho if enable_echo_afterwards
end
- say("#{echo}\n")
end
@question.change_case(response)
end
@@ -96,7 +96,7 @@ def get_character( input = STDIN )
CHARACTER_MODE = "ncurses" # For Debugging purposes only.
#
- # ncurses savvy getc(). (JRuby choice.)
+ # ncurses savvy getc().
#
def get_character( input = STDIN )
FFI::NCurses.initscr
@@ -110,13 +110,6 @@ def get_character( input = STDIN )
end
rescue LoadError => e # If the ffi-ncurses choice fails, try using stty
- if JRUBY
- if e.message =~ /^no such file to load/
- STDERR.puts "\n*** Using highline effectively in JRuby requires manually installing the ffi-ncurses gem.\n*** jruby -S gem install ffi-ncurses"
- else
- raise
- end
- end
CHARACTER_MODE = "stty" # For Debugging purposes only.
#

0 comments on commit fc255ba

Please sign in to comment.