readline-ng 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ gemfile: Gemfile.travis
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.2
6
+ - 1.9.3
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ group :test do
4
+ gem "rake"
5
+ gem "rspec"
6
+ gem "mocha"
7
+ end
8
+
@@ -0,0 +1,21 @@
1
+ ## Readline ng
2
+
3
+ [![Build Status](https://secure.travis-ci.org/richoH/readline-ng.png?branch=master)](http://travis-ci.org/richoH/readline-ng)
4
+
5
+ Readline-NG is /not/ a drop in replacement for readline.
6
+
7
+ It addresses a very specific need I had inside a twitter client, but
8
+ hopefully it's of use to someone else, too.
9
+
10
+ Readline relies on being able to poll for input often, leading to a
11
+ hideously inefficient event loop, but generally
12
+ ```ruby
13
+ reader = ReadlineNG::Reader.new
14
+ loop do
15
+ reader.tick
16
+ reader.each_line do |line|
17
+ # Handle full line of input
18
+ reader.puts_above("user input #{line}")
19
+ end
20
+ end
21
+ ```
@@ -0,0 +1,9 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.pattern = "spec/*_spec.rb"
6
+ end
7
+
8
+ desc 'Default: run specs'
9
+ task :default => :spec
@@ -2,7 +2,7 @@ module ReadlineNG
2
2
 
3
3
  VERSION_MAJOR = 0
4
4
  VERSION_MINOR = 0
5
- VERSION_PATCH = 5
5
+ VERSION_PATCH = 6
6
6
  VERSION = "#{VERSION_MAJOR}.#{VERSION_MINOR}.#{VERSION_PATCH}"
7
7
 
8
8
  CONTROL_BS = "\x08"
@@ -13,6 +13,9 @@ module ReadlineNG
13
13
  KB_BS = "\x7F"
14
14
  KB_CR = "\x0d"
15
15
 
16
+ KB_LEFT = "\x25"
17
+ KB_RIGHT = "\x27"
18
+
16
19
  BLANK = " "
17
20
 
18
21
  class Reader
@@ -23,16 +26,18 @@ module ReadlineNG
23
26
  # make a whole lot of sense, although potentially giving out rope is not a
24
27
  # terrible idea here
25
28
 
26
- attr_accessor :lines, :visible
29
+ attr_accessor :lines, :visible, :polling_resolution
27
30
 
28
31
  # A third party dev can overload filter to implement their own actions
29
32
  def filter
30
33
  end
31
34
 
32
- def initialize(visible=true)
35
+ def initialize(visible=true, opts = {})
33
36
  @buf = ""
37
+ @index = 0
34
38
  @visible = visible
35
39
  @lines = []
40
+ @polling_resolution = opts[:polling_resolution] || 20
36
41
  if @@initialized
37
42
  STDERR.puts "A ReadlineNG reader is already instanciated, expect weirdness"
38
43
  else
@@ -45,6 +50,13 @@ module ReadlineNG
45
50
  end
46
51
  end
47
52
 
53
+ def wait(n)
54
+ (n * polling_resolution).times do
55
+ tick
56
+ sleep 1.0/polling_resolution
57
+ end
58
+ end
59
+
48
60
  def puts_above(string)
49
61
  if visible
50
62
  backspace(@buf.length)
@@ -58,14 +70,6 @@ module ReadlineNG
58
70
  t = STDIN.read_nonblock(128)
59
71
  t.each_char { |c| process(c) }
60
72
  filter # Expect a 3rd party dev to override this
61
-
62
- raise Interrupt if @buf.include?(CONTROL_INT)
63
-
64
- a = @buf.split("\r")
65
- return if a.empty? && @buf.empty?
66
- @buf = @buf[-1] == "\r" ? "" : a.pop
67
-
68
- @lines += a
69
73
  rescue Errno::EAGAIN
70
74
  nil
71
75
  end
@@ -87,16 +91,48 @@ module ReadlineNG
87
91
  private
88
92
 
89
93
  def process(c)
94
+ # TODO This method is getting monolithic, think about how to modularise it
90
95
  case c
96
+ when "\r"
97
+ @lines += [@buf]
98
+ reset
99
+ when CONTROL_INT
100
+ raise Interrupt
91
101
  when KB_BS
92
- @buf.chop!
93
- backspace
102
+ if @buf.chop!
103
+ @index -= 1
104
+ backspace
105
+ end
106
+ when KB_LEFT
107
+ if @buf and @index != 0
108
+ @index -= 1
109
+ end
110
+ when KB_RIGHT
111
+ if @buf and @index < @buf.length
112
+ @index -= 1
113
+ end
94
114
  else
95
- @buf += c
96
- _print c
115
+ @buf = @buf.insert(@index, c)
116
+ @index += 1
117
+ if @index == @buf.length
118
+ _print c
119
+ else
120
+ redraw
121
+ end
97
122
  end
98
123
  end
99
124
 
125
+ def reset
126
+ @index, @buf = 0, ""
127
+ end
128
+
129
+ def redraw
130
+ # TODO We can get away with only going back as far as index, I should
131
+ # think
132
+ backspace(@buf.length)
133
+ _print @buf
134
+ end
135
+
100
136
  def backspace(n=1)
101
137
  _print CONTROL_BS*n,BLANK*n,CONTROL_BS*n
102
138
  end
@@ -118,8 +154,6 @@ module ReadlineNG
118
154
  `stty #{@stty_saved}`
119
155
  end
120
156
 
121
-
122
-
123
157
  end
124
158
  end
125
159
 
@@ -12,6 +12,8 @@ Gem::Specification.new do |s|
12
12
  s.description = s.summary
13
13
 
14
14
  s.add_development_dependency 'rspec'
15
+ s.add_development_dependency 'mocha'
16
+ s.add_development_dependency 'rake'
15
17
 
16
18
  s.files = `git ls-files`.split("\n")
17
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -58,5 +58,25 @@ describe ReadlineNG do
58
58
  @reader.get_line.should == "input"
59
59
  end
60
60
 
61
+ it "should respect the left key" do
62
+ STDIN.stub(:read_nonblock).and_return("asdf", "\x25"*2, "__\r")
63
+ @reader.get_line.should == "as__df"
64
+ end
65
+
66
+ it "should not allow the user to left before an empty buffer" do
67
+ STDIN.stub(:read_nonblock).and_return("\x25"*2, "__", "\x25"*2, "\r")
68
+ @reader.get_line.should == "__"
69
+ end
70
+
71
+ it "should respect the right key" do
72
+ STDIN.stub(:read_nonblock).and_return("asdf", "\x25"*2, "__", "\x27", "++\r" )
73
+ @reader.get_line.should == "as_++_df"
74
+ end
75
+
76
+ it "should not allow the user to right after an empty buffer" do
77
+ STDIN.stub(:read_nonblock).and_return("\x27"*2, "__", "\x27"*2, "\r")
78
+ @reader.get_line.should == "__"
79
+ end
80
+
61
81
  end
62
82
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: readline-ng
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-22 00:00:00.000000000 Z
12
+ date: 2012-03-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &7211240 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,44 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *7211240
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mocha
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
25
62
  description: Essentially, readline++
26
63
  email:
27
64
  - richo@psych0tik.net
@@ -30,8 +67,11 @@ extensions: []
30
67
  extra_rdoc_files: []
31
68
  files:
32
69
  - .rvmrc
70
+ - .travis.yml
33
71
  - Gemfile
34
- - README
72
+ - Gemfile.travis
73
+ - README.md
74
+ - Rakefile
35
75
  - lib/readline-ng.rb
36
76
  - readline-ng.gemspec
37
77
  - spec/readline-ng_spec.rb
@@ -55,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
95
  version: '0'
56
96
  requirements: []
57
97
  rubyforge_project:
58
- rubygems_version: 1.8.16
98
+ rubygems_version: 1.8.19
59
99
  signing_key:
60
100
  specification_version: 3
61
101
  summary: Essentially, readline++
data/README DELETED
@@ -1,16 +0,0 @@
1
- Readline-NG is /not/ a drop in replacement for readline.
2
-
3
- It addresses a very specific need I had inside a twitter client, but
4
- hopefully it's of use to someone else, too.
5
-
6
- Readline relies on being able to poll for input often, leading to a
7
- hideously inefficient event loop, but generally
8
-
9
- reader = ReadlineNG::Reader.new
10
- loop do
11
- reader.tick
12
- reader.each_line do |line|
13
- # Handle full line of input
14
- reader.puts_above("user input #{line}")
15
- end
16
- end