ripl-readline-em 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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