ripl-readline-em 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gemspec CHANGED
@@ -12,14 +12,10 @@ Gem::Specification.new do |s|
12
12
  s.summary = "A ripl plugin to run readline within eventmachine"
13
13
  s.description = "Run EventMachine code in a ripl shell asynchronously with readline editing and completion"
14
14
  s.required_rubygems_version = ">= 1.3.6"
15
-
16
15
  s.add_dependency 'ripl', '>= 0.4.2'
17
16
  s.add_dependency 'eventmachine'
18
17
  s.add_dependency 'ffi'
19
-
20
- s.add_development_dependency 'bacon', '>= 1.1.0'
21
-
22
- s.files = Dir.glob(%w[lib/**/*.rb [A-Z]*.{txt,rdoc}]) + %w{Rakefile .gemspec}
18
+ s.files = Dir.glob(%w[lib/**/*.rb [A-Z]*.{txt,rdoc} examples/**/*.rb]) + %w{Rakefile .gemspec}
23
19
  s.extra_rdoc_files = ["README.rdoc", "LICENSE.txt"]
24
20
  s.license = 'MIT'
25
21
  end
@@ -11,24 +11,5 @@ Install the gem with:
11
11
 
12
12
  == Usage
13
13
 
14
- require 'ripl/readline/em'
14
+ :include: ./examples/ripl_readline_em.rb
15
15
 
16
- EventMachine.run do
17
- EventMachine.add_periodic_timer(2) do
18
- # example writing output while line is being edited
19
- puts "#{Time.now}"
20
- Readline.refresh_line
21
- end
22
-
23
- Ripl.start # exiting ripl shell shuts down EventMachine
24
- end
25
-
26
- Writing output to stdout writes over the current input line. A call
27
- to Readline.refresh_line fixes things up, but a copy of the prompt and
28
- any input text follows along with the line of output. I suspect this
29
- isn't the best way...
30
-
31
- == Todo
32
-
33
- Improve technique of being able to write output without messing up the
34
- input line.
data/Rakefile CHANGED
@@ -29,7 +29,7 @@ end
29
29
 
30
30
  desc 'Run tests'
31
31
  task :test do |t|
32
- sh 'bacon -q -Ilib -I. test/**_test.rb'
32
+ sh 'bacon -q -Ilib -I. test/*_test.rb'
33
33
  end
34
34
 
35
35
  task :default => :test
@@ -0,0 +1,14 @@
1
+ require 'readline/callback.rb'
2
+
3
+ Readline::callback_handler_install('> ') do |line|
4
+ puts "have a line: #{line}"
5
+ end
6
+
7
+ begin
8
+ loop do
9
+ select [$stdin]
10
+ Readline::callback_read_char
11
+ end
12
+ ensure
13
+ Readline::callback_handler_remove
14
+ end
@@ -0,0 +1,34 @@
1
+ require 'eventmachine'
2
+ require 'ripl/readline/em'
3
+
4
+ EventMachine.run do
5
+ EventMachine.add_periodic_timer(2) do
6
+ # Example of writing output while line is being edited.
7
+ #
8
+ # See also http://stackoverflow.com/questions/1512028/gnu-readline-how-do-clear-the-input-line
9
+ print "\b \b" * Readline.line_buffer.size
10
+ print "\r"
11
+ begin
12
+ puts "#{Time.now}"
13
+ ensure
14
+ Readline.forced_update_display
15
+ end
16
+ end
17
+
18
+ # Start up Ripl, but it will not receive any user input
19
+ Ripl.start
20
+
21
+ # Watch stdin for input, sending it to Ripl as entered (including editing,
22
+ # history and completion).
23
+ #
24
+ # Default behavior is to call EventMachine.stop_event_loop when the shell is
25
+ # exited. Modify this behavior by passing a hash with an `:on_exit` entry,
26
+ # either nil or a Proc that will be run on exit instead of the default.
27
+ EventMachine.watch_stdin Ripl::Readline::EmInput
28
+
29
+ # -or-
30
+ # EventMachine.watch_stdin Ripl::Readline::EmInput, :on_exit => nil
31
+
32
+ # Yet another option is to create your own handler module, include
33
+ # Ripl::Readline::EmInput, and override the `on_exit` method.
34
+ end
@@ -1,4 +1,5 @@
1
1
  require 'ffi'
2
+ require 'readline'
2
3
 
3
4
  module Readline
4
5
  # An alternate, callback-based interface to Readline for use in a
@@ -11,7 +12,15 @@ module Readline
11
12
  module Callback
12
13
  extend FFI::Library
13
14
 
14
- ffi_lib 'readline'
15
+ def self.editline?
16
+ @__is_editline__ ||= (Readline::VERSION rescue nil).to_s[/editline/i]
17
+ end
18
+
19
+ if editline?
20
+ ffi_lib 'edit'
21
+ else
22
+ ffi_lib 'readline'
23
+ end
15
24
 
16
25
  callback :rl_vcpfunc_t, [:string], :void
17
26
  attach_function :rl_callback_handler_install, [:string, :rl_vcpfunc_t], :void
@@ -19,8 +28,15 @@ module Readline
19
28
  attach_function :rl_callback_handler_remove, [], :void
20
29
 
21
30
  # as-is functions
31
+ attach_function :forced_update_display, :rl_forced_update_display, [], :void
22
32
 
23
- attach_function :set_prompt, :rl_set_prompt, [:string], :int
33
+ if editline?
34
+ def set_prompt(*args)
35
+ # noop; rl_set_prompt isn't exported by EditLine
36
+ end
37
+ else
38
+ attach_function :set_prompt, :rl_set_prompt, [:string], :int
39
+ end
24
40
 
25
41
  # Set up the terminal for readline I/O and display the initial
26
42
  # expanded value of prompt. Save the value of `block` to call when a
@@ -51,7 +67,6 @@ module Readline
51
67
  # Readline's use again. EOF is indicated by calling handler with a
52
68
  # NULL line.
53
69
  def callback_read_char
54
- $stderr.puts "reading char"
55
70
  rl_callback_read_char
56
71
  end
57
72
 
@@ -2,95 +2,29 @@ require 'eventmachine'
2
2
  require 'readline/callback'
3
3
  require 'ripl'
4
4
  require 'ripl/readline'
5
+ require 'ripl/readline/eminput'
5
6
 
6
7
  module Ripl
7
8
  module Readline
8
9
  module Em
9
- module InputHandler
10
- def notify_readable
11
- $stderr.puts "is readable"
12
- ::Readline.callback_read_char
13
- $stderr.puts "done"
14
- end
15
-
16
- def unbind
17
- $stderr.puts "unbind!"
18
- ::Readline.callback_handler_remove
19
- end
20
- end
21
- end
22
- end
23
- end
24
-
25
- module Ripl
26
- module Readline
27
- module Em
28
- VERSION = '0.1.0'
10
+ VERSION = '0.2.0'
29
11
 
30
12
  def get_input
31
13
  history << @input
32
14
  @input
33
15
  end
34
16
 
35
- def redisplay
36
- ::Readline.set_prompt(Ripl.shell.prompt)
37
- ::Readline.refresh_line
38
- end
39
-
40
- def handle_line(line)
41
- catch(:normal_exit) do
42
- catch(:ripl_exit) do
43
- throw :ripl_exit unless line # line = nil implies EOF
44
-
45
- $stderr.puts "have line #{line}"
46
-
47
- Ripl.shell.input = line
48
- Ripl.shell.loop_once
49
- redisplay
50
- throw :normal_exit
51
- end
52
-
53
- # If we got here, it means :ripl_exit was caught
54
- ::Readline.callback_handler_remove
55
- after_loop
56
- end
57
- end
58
-
59
- def loop_override
60
- before_loop
61
-
62
- ::Readline.callback_handler_install do |line|
63
- EventMachine.next_tick { handle_line(line) }
64
- end
65
-
66
- # is hardcoded $stdin always appropriate?
67
- conn = EventMachine.watch $stdin, InputHandler
68
- conn.notify_readable = true
69
-
70
- redisplay
71
- end
72
-
73
- def before_loop
74
- super
75
- trap('SIGINT') { handle_interrupt }
76
- end
77
-
78
- def after_loop
79
- super
80
- EventMachine.stop_event_loop
81
- end
82
-
83
- def handle_interrupt
84
- super
85
- redisplay
17
+ def async_loop
18
+ # no-op; functionality is done asynchronously
86
19
  end
87
20
  end
88
21
  end
89
22
  end
90
23
 
91
24
  Ripl::Shell.include Ripl::Readline::Em
25
+
92
26
  class Ripl::Shell
93
27
  def loop
94
- loop_override
28
+ async_loop
95
29
  end
96
30
  end
@@ -0,0 +1,69 @@
1
+ module EventMachine
2
+ # Convenience method to add a watch on `STDIN` and set
3
+ # notify_readable to `true`.
4
+ #
5
+ # See EventMachine.watch
6
+ def self.watch_stdin(handler, *args)
7
+ conn = EventMachine.watch $stdin, handler, *args
8
+ conn.notify_readable = true
9
+ conn
10
+ end
11
+ end
12
+
13
+ module Ripl
14
+ module Readline
15
+ module EmInput
16
+ def initialize(opts = {})
17
+ super()
18
+ @on_exit = opts[:on_exit] || proc { EventMachine.stop_event_loop }
19
+ handler_install
20
+ Ripl.shell.before_loop
21
+ trap('SIGINT') { handle_interrupt }
22
+ end
23
+
24
+ def notify_readable
25
+ ::Readline.callback_read_char
26
+ end
27
+
28
+ def unbind
29
+ super
30
+ ::Readline.callback_handler_remove
31
+ Ripl.shell.after_loop
32
+ on_exit
33
+ end
34
+
35
+ def on_exit
36
+ @on_exit.call if @on_exit
37
+ end
38
+
39
+ def receive_line(line)
40
+ catch(:normal_exit) do
41
+ catch(:ripl_exit) do
42
+ throw :ripl_exit unless line # line = nil implies EOF
43
+
44
+ Ripl.shell.input = line
45
+ Ripl.shell.loop_once
46
+ handler_install # EditLine requires handler be
47
+ # reinstalled for each line.
48
+ # Seems harmless for Readline
49
+ throw :normal_exit
50
+ end
51
+ detach # :ripl_exit
52
+ end
53
+ # :normal_exit
54
+ end
55
+
56
+ def handle_interrupt
57
+ ::Readline.callback_handler_remove
58
+ puts
59
+ handler_install
60
+ end
61
+
62
+ def handler_install
63
+ ::Readline.callback_handler_install(Ripl.shell.prompt) do |line|
64
+ EventMachine.next_tick { receive_line(line) }
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ripl-readline-em
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-25 00:00:00.000000000 -06:00
13
- default_executable:
12
+ date: 2011-12-02 00:00:00.000000000Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: ripl
17
- requirement: &8353400 !ruby/object:Gem::Requirement
16
+ requirement: &8372840 !ruby/object:Gem::Requirement
18
17
  none: false
19
18
  requirements:
20
19
  - - ! '>='
@@ -22,10 +21,10 @@ dependencies:
22
21
  version: 0.4.2
23
22
  type: :runtime
24
23
  prerelease: false
25
- version_requirements: *8353400
24
+ version_requirements: *8372840
26
25
  - !ruby/object:Gem::Dependency
27
26
  name: eventmachine
28
- requirement: &8352820 !ruby/object:Gem::Requirement
27
+ requirement: &8372300 !ruby/object:Gem::Requirement
29
28
  none: false
30
29
  requirements:
31
30
  - - ! '>='
@@ -33,10 +32,10 @@ dependencies:
33
32
  version: '0'
34
33
  type: :runtime
35
34
  prerelease: false
36
- version_requirements: *8352820
35
+ version_requirements: *8372300
37
36
  - !ruby/object:Gem::Dependency
38
37
  name: ffi
39
- requirement: &8314360 !ruby/object:Gem::Requirement
38
+ requirement: &8371620 !ruby/object:Gem::Requirement
40
39
  none: false
41
40
  requirements:
42
41
  - - ! '>='
@@ -44,18 +43,7 @@ dependencies:
44
43
  version: '0'
45
44
  type: :runtime
46
45
  prerelease: false
47
- version_requirements: *8314360
48
- - !ruby/object:Gem::Dependency
49
- name: bacon
50
- requirement: &8313560 !ruby/object:Gem::Requirement
51
- none: false
52
- requirements:
53
- - - ! '>='
54
- - !ruby/object:Gem::Version
55
- version: 1.1.0
56
- type: :development
57
- prerelease: false
58
- version_requirements: *8313560
46
+ version_requirements: *8371620
59
47
  description: Run EventMachine code in a ripl shell asynchronously with readline editing
60
48
  and completion
61
49
  email: pat@polycrystal.org
@@ -66,13 +54,14 @@ extra_rdoc_files:
66
54
  - LICENSE.txt
67
55
  files:
68
56
  - lib/ripl/readline/em.rb
69
- - lib/readline_cb.rb
57
+ - lib/ripl/readline/eminput.rb
70
58
  - lib/readline/callback.rb
71
59
  - LICENSE.txt
72
60
  - README.rdoc
61
+ - examples/readline_callback.rb
62
+ - examples/ripl_readline_em.rb
73
63
  - Rakefile
74
64
  - .gemspec
75
- has_rdoc: true
76
65
  homepage: http://github.com/pmahoney/ripl-readline-em
77
66
  licenses:
78
67
  - MIT
@@ -94,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
83
  version: 1.3.6
95
84
  requirements: []
96
85
  rubyforge_project:
97
- rubygems_version: 1.6.2
86
+ rubygems_version: 1.8.10
98
87
  signing_key:
99
88
  specification_version: 3
100
89
  summary: A ripl plugin to run readline within eventmachine
@@ -1,37 +0,0 @@
1
- require 'readline/alt'
2
-
3
- module Readline::Alt::Demo
4
- class << self
5
- # Demonstration method to read a line of input using the callback
6
- # functions rather than a direct call to Readline#readline.
7
- def readline(prompt = nil)
8
- readline_string = nil
9
-
10
- Readline.handler_install(prompt) do |str|
11
- readline_string = str
12
- end
13
-
14
- begin
15
- Readline.read_char until readline_string
16
- ensure
17
- Readline.handler_remove
18
- end
19
-
20
- readline_string
21
- end
22
- end
23
- end
24
-
25
- #line = Readline::Alt::Demo.readline('> ')
26
- #puts "READ A LINE::: #{line.inspect}"
27
-
28
- require 'ripl/readline/em'
29
-
30
- EventMachine.run do
31
- EventMachine.add_periodic_timer(2) do
32
- puts "#{Time.now} alive!"
33
- Readline.refresh_line
34
- end
35
-
36
- Ripl.start
37
- end