tty-reader 0.7.0 → 0.8.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/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