tty-reader 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile DELETED
@@ -1,10 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require "bundler/gem_tasks"
4
-
5
- FileList['tasks/**/*.rake'].each(&method(:import))
6
-
7
- desc 'Run all specs'
8
- task ci: %w[ spec ]
9
-
10
- task default: :spec
@@ -1,34 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'tty-reader'
3
-
4
- input = StringIO.new("a")
5
- output = StringIO.new
6
- $stdin = input
7
- reader = TTY::Reader.new(input, output)
8
-
9
- Benchmark.ips do |x|
10
- x.report('getc') do
11
- input.rewind
12
- $stdin.getc
13
- end
14
-
15
- x.report('read_char') do
16
- input.rewind
17
- reader.read_char
18
- end
19
-
20
- x.compare!
21
- end
22
-
23
- # v0.1.0
24
- #
25
- # Calculating -------------------------------------
26
- # getc 52462 i/100ms
27
- # read_char 751 i/100ms
28
- # -------------------------------------------------
29
- # getc 2484819.4 (±4.1%) i/s - 12433494 in 5.013438s
30
- # read_char 7736.4 (±2.9%) i/s - 39052 in 5.052628s
31
- #
32
- # Comparison:
33
- # getc: 2484819.4 i/s
34
- # read_char: 7736.4 i/s - 321.19x slower
@@ -1,34 +0,0 @@
1
- require 'benchmark/ips'
2
- require 'tty-reader'
3
-
4
- input = StringIO.new("abc\n")
5
- output = StringIO.new
6
- $stdin = input
7
- reader = TTY::Reader.new(input, output)
8
-
9
- Benchmark.ips do |x|
10
- x.report('gets') do
11
- input.rewind
12
- $stdin.gets
13
- end
14
-
15
- x.report('read_line') do
16
- input.rewind
17
- reader.read_line
18
- end
19
-
20
- x.compare!
21
- end
22
-
23
- # v0.1.0
24
- #
25
- # Calculating -------------------------------------
26
- # gets 51729 i/100ms
27
- # read_line 164 i/100ms
28
- # -------------------------------------------------
29
- # gets 1955255.2 (±3.7%) i/s - 9776781 in 5.008004s
30
- # read_line 1215.1 (±33.1%) i/s - 5248 in 5.066569s
31
- #
32
- # Comparison:
33
- # gets: 1955255.2 i/s
34
- # read_line: 1215.1 i/s - 1609.19x slower
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "tty/reader"
5
- require "irb"
6
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,16 +0,0 @@
1
- require_relative '../lib/tty-reader'
2
-
3
- reader = TTY::Reader.new
4
-
5
- puts "Press a key (or Ctrl-X to exit)"
6
-
7
- loop do
8
- print "=> "
9
- char = reader.read_keypress
10
- if ?\C-x == char
11
- puts "Exiting..."
12
- exit
13
- else
14
- puts "#{char.inspect} [#{char.ord}] (hex: #{char.ord.to_s(16)})"
15
- end
16
- end
@@ -1,17 +0,0 @@
1
- require_relative '../lib/tty-reader'
2
-
3
- reader = TTY::Reader.new
4
-
5
- puts "Press a key (or Ctrl-X to exit)"
6
-
7
- loop do
8
- print reader.cursor.clear_line
9
- print "=> "
10
- char = reader.read_keypress(nonblock: true)
11
- if ?\C-x == char
12
- puts "Exiting..."
13
- exit
14
- elsif char
15
- puts "#{char.inspect} [#{char.ord}] (hex: #{char.ord.to_s(16)})"
16
- end
17
- end
@@ -1,7 +0,0 @@
1
- require_relative '../lib/tty-reader'
2
-
3
- reader = TTY::Reader.new
4
-
5
- answer = reader.read_line(">> ")
6
-
7
- puts "answer: #{answer}"
@@ -1,9 +0,0 @@
1
- require_relative "../lib/tty-reader"
2
-
3
- reader = TTY::Reader.new
4
-
5
- reader.on(:keyctrl_x, :keyescape) { puts "Exiting..."; exit }
6
-
7
- loop do
8
- reader.read_line("one\ntwo\nthree")
9
- end
@@ -1,7 +0,0 @@
1
- require_relative '../lib/tty-reader'
2
-
3
- reader = TTY::Reader.new
4
-
5
- answer = reader.read_multiline(">> ")
6
-
7
- puts "\nanswer: #{answer}"
@@ -1,6 +0,0 @@
1
- require_relative '../lib/tty-reader'
2
-
3
- reader = TTY::Reader.new
4
-
5
- answer = reader.read_line('=> ', echo: false)
6
- puts "Answer: #{answer}"
@@ -1,12 +0,0 @@
1
- require_relative '../lib/tty-reader'
2
-
3
- puts "*** TTY::Reader Shell ***"
4
- puts "Press Ctrl-X or ESC to exit"
5
-
6
- reader = TTY::Reader.new
7
-
8
- reader.on(:keyctrl_x, :keyescape) { puts "Exiting..."; exit }
9
-
10
- loop do
11
- reader.read_line('=> ')
12
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- if ENV['COVERAGE'] || ENV['TRAVIS']
4
- require 'simplecov'
5
- require 'coveralls'
6
-
7
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
8
- SimpleCov::Formatter::HTMLFormatter,
9
- Coveralls::SimpleCov::Formatter
10
- ])
11
-
12
- SimpleCov.start do
13
- command_name 'spec'
14
- add_filter 'spec'
15
- end
16
- end
17
-
18
- require "bundler/setup"
19
- require "tty-reader"
20
-
21
- class StringIO
22
- def wait_readable(*)
23
- true
24
- end
25
- end
26
-
27
- RSpec.configure do |config|
28
- # Enable flags like --only-failures and --next-failure
29
- config.example_status_persistence_file_path = ".rspec_status"
30
-
31
- config.mock_with :rspec do |mocks|
32
- mocks.verify_partial_doubles = true
33
- end
34
-
35
- # Disable RSpec exposing methods globally on `Module` and `main`
36
- config.disable_monkey_patching!
37
-
38
- # This setting enables warnings. It's recommended, but in some cases may
39
- # be too noisy due to issues in dependencies.
40
- config.warnings = true
41
-
42
- if config.files_to_run.one?
43
- config.default_formatter = 'doc'
44
- end
45
-
46
- config.profile_examples = 2
47
-
48
- config.order = :random
49
-
50
- Kernel.srand config.seed
51
- end
@@ -1,177 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe TTY::Reader::History do
4
- it "has no lines" do
5
- history = described_class.new
6
- expect(history.size).to eq(0)
7
- end
8
-
9
- it "doesn't navigate through empty buffer" do
10
- history = described_class.new
11
- expect(history.next?).to eq(false)
12
- expect(history.previous?).to eq(false)
13
- end
14
-
15
- it "allows to cycle through non-empty buffer" do
16
- history = described_class.new(3, cycle: true)
17
- history << "line"
18
- expect(history.next?).to eq(true)
19
- expect(history.previous?).to eq(true)
20
- end
21
-
22
- it "defaults maximum size" do
23
- history = described_class.new
24
- expect(history.max_size).to eq(512)
25
- end
26
-
27
- it "presents string representation" do
28
- history = described_class.new
29
- expect(history.to_s).to eq("[]")
30
- end
31
-
32
- it "adds items to history without overflowing" do
33
- history = described_class.new(3)
34
- history << "line #1"
35
- history << "line #2"
36
- history << "line #3"
37
- history << "line #4"
38
-
39
- expect(history.to_a).to eq(["line #2", "line #3", "line #4"])
40
- expect(history.index).to eq(2)
41
- end
42
-
43
- it "excludes items" do
44
- exclude = proc { |line| /line #[23]/.match(line) }
45
- history = described_class.new(exclude: exclude)
46
- history << "line #1"
47
- history << "line #2"
48
- history << "line #3"
49
-
50
- expect(history.to_a).to eq(["line #1"])
51
- expect(history.index).to eq(0)
52
- end
53
-
54
- it "allows duplicates" do
55
- history = described_class.new
56
- history << "line #1"
57
- history << "line #1"
58
- history << "line #1"
59
-
60
- expect(history.to_a).to eq(["line #1", "line #1", "line #1"])
61
- end
62
-
63
- it "prevents duplicates" do
64
- history = described_class.new(duplicates: false)
65
- history << "line #1"
66
- history << "line #1"
67
- history << "line #1"
68
-
69
- expect(history.to_a).to eq(["line #1"])
70
- end
71
-
72
- it "navigates through history buffer without cycling" do
73
- history = described_class.new(3)
74
- history << "line #1"
75
- history << "line #2"
76
- history << "line #3"
77
-
78
- expect(history.index).to eq(2)
79
- history.previous
80
- history.previous
81
- expect(history.index).to eq(0)
82
- history.previous
83
- expect(history.index).to eq(0)
84
- history.next
85
- history.next
86
- expect(history.index).to eq(2)
87
- history.next
88
- expect(history.next?).to eq(false)
89
- expect(history.index).to eq(2)
90
- end
91
-
92
- it "navigates through history buffer with cycling" do
93
- history = described_class.new(3, cycle: true)
94
- history << "line #1"
95
- history << "line #2"
96
- history << "line #3"
97
-
98
- expect(history.index).to eq(2)
99
- history.previous
100
- history.previous
101
- expect(history.index).to eq(0)
102
- history.previous
103
- expect(history.index).to eq(2)
104
- expect(history.next?).to eq(true)
105
- history.next
106
- history.next
107
- expect(history.index).to eq(1)
108
- history.next
109
- expect(history.index).to eq(2)
110
- end
111
-
112
- it "checks if navigation is possible" do
113
- history = described_class.new(3)
114
-
115
- expect(history.index).to eq(nil)
116
- expect(history.previous?).to eq(false)
117
- expect(history.next?).to eq(false)
118
-
119
- history << "line #1"
120
- history << "line #2"
121
- expect(history.index).to eq(1)
122
- expect(history.previous?).to eq(true)
123
- expect(history.next?).to eq(false)
124
-
125
- history.previous
126
- expect(history.index).to eq(0)
127
- expect(history.previous?).to eq(true)
128
- expect(history.next?).to eq(true)
129
-
130
- history.previous
131
- expect(history.index).to eq(0)
132
- expect(history.previous?).to eq(true)
133
- expect(history.next?).to eq(true)
134
- end
135
-
136
- it "gets line based on index" do
137
- history = described_class.new(3, cycle: true)
138
- history << "line #1"
139
- history << "line #2"
140
- history << "line #3"
141
-
142
- expect(history[-1]).to eq('line #3')
143
- expect(history[1]).to eq('line #2')
144
- expect {
145
- history[11]
146
- }.to raise_error(IndexError, 'invalid index')
147
- end
148
-
149
- it "retrieves current line" do
150
- history = described_class.new(3, cycle: true)
151
- expect(history.get).to eq(nil)
152
-
153
- history << "line #1"
154
- history << "line #2"
155
- history << "line #3"
156
-
157
- expect(history.get).to eq("line #3")
158
- history.previous
159
- history.previous
160
- expect(history.get).to eq("line #1")
161
- history.next
162
- expect(history.get).to eq("line #2")
163
- end
164
-
165
- it "clears all lines" do
166
- history = described_class.new(3)
167
-
168
- history << "line #1"
169
- history << "line #2"
170
- history << "line #3"
171
-
172
- expect(history.size).to eq(3)
173
- history.clear
174
- expect(history.size).to eq(0)
175
- expect(history.index).to eq(0)
176
- end
177
- end
@@ -1,102 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'shellwords'
4
-
5
- RSpec.describe TTY::Reader::KeyEvent, '#from' do
6
- let(:keys) { TTY::Reader::Keys.keys }
7
-
8
- it "parses backspace" do
9
- event = described_class.from(keys, "\x7f")
10
- expect(event.key.name).to eq(:backspace)
11
- expect(event.value).to eq("\x7f")
12
- end
13
-
14
- it "parses lowercase char" do
15
- event = described_class.from(keys, 'a')
16
- expect(event.key.name).to eq(:alpha)
17
- expect(event.value).to eq('a')
18
- end
19
-
20
- it "parses uppercase char" do
21
- event = described_class.from(keys, 'A')
22
- expect(event.key.name).to eq(:alpha)
23
- expect(event.value).to eq('A')
24
- end
25
-
26
- it "parses number char" do
27
- event = described_class.from(keys, '666')
28
- expect(event.key.name).to eq(:num)
29
- expect(event.value).to eq('666')
30
- end
31
-
32
- it "parses ctrl-a to ctrl-z inputs" do
33
- (1..26).zip('a'..'z').each do |code, char|
34
- event = described_class.from(TTY::Reader::Keys.ctrl_keys, code.chr)
35
- expect(event.key.name).to eq(:"ctrl_#{char}")
36
- expect(event.value).to eq(code.chr)
37
- end
38
- end
39
-
40
- it "parses uknown key" do
41
- no_keys = {}
42
- event = described_class.from(no_keys, '*')
43
- expect(event.key.name).to eq(:ignore)
44
- expect(event.value).to eq('*')
45
- end
46
-
47
- it "exposes line value" do
48
- event = described_class.from(keys, 'c', 'ab')
49
- expect(event.line).to eq('ab')
50
- end
51
-
52
- # F1-F12 keys
53
- {
54
- f1: ["\eOP","\e[[A","\e[11~"],
55
- f2: ["\eOQ","\e[[B","\e[12~"],
56
- f3: ["\eOR","\e[[C","\e[13~"],
57
- f4: ["\eOS","\e[[D","\e[14~"],
58
- f5: [ "\e[[E","\e[15~"],
59
- f6: [ "\e[17~"],
60
- f7: [ "\e[18~"],
61
- f8: [ "\e[19~"],
62
- f9: [ "\e[20~"],
63
- f10: [ "\e[21~"],
64
- f11: [ "\e[23~"],
65
- f12: [ "\e[24~"]
66
- }.each do |name, codes|
67
- codes.each do |code|
68
- it "parses #{Shellwords.escape(code)} as #{name} key" do
69
- event = described_class.from(keys, code)
70
- expect(event.key.name).to eq(name)
71
- expect(event.key.meta).to eq(false)
72
- expect(event.key.ctrl).to eq(false)
73
- expect(event.key.shift).to eq(false)
74
- end
75
- end
76
- end
77
-
78
- # arrow keys & text editing
79
- {
80
- up: ["\e[A"],
81
- down: ["\e[B"],
82
- right: ["\e[C"],
83
- left: ["\e[D"],
84
- clear: ["\e[E"],
85
- home: ["\e[1~", "\e[7~", "\e[H"],
86
- end: ["\e[4~", "\eOF", "\e[F"],
87
- insert: ["\e[2~"],
88
- delete: ["\e[3~"],
89
- page_up: ["\e[5~"],
90
- page_down: ["\e[6~"]
91
- }.each do |name, codes|
92
- codes.each do |code|
93
- it "parses #{Shellwords.escape(code)} as #{name} key" do
94
- event = described_class.from(keys, code)
95
- expect(event.key.name).to eq(name)
96
- expect(event.key.meta).to eq(false)
97
- expect(event.key.ctrl).to eq(false)
98
- expect(event.key.shift).to eq(false)
99
- end
100
- end
101
- end
102
- end