tty-reader 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +25 -0
- data/CHANGELOG.md +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +21 -0
- data/LICENSE.txt +21 -0
- data/README.md +187 -0
- data/Rakefile +10 -0
- data/appveyor.yml +25 -0
- data/bin/console +6 -0
- data/bin/setup +8 -0
- data/lib/tty-reader.rb +3 -0
- data/lib/tty/reader.rb +348 -0
- data/lib/tty/reader/codes.rb +120 -0
- data/lib/tty/reader/console.rb +56 -0
- data/lib/tty/reader/history.rb +144 -0
- data/lib/tty/reader/key_event.rb +90 -0
- data/lib/tty/reader/line.rb +161 -0
- data/lib/tty/reader/mode.rb +43 -0
- data/lib/tty/reader/version.rb +7 -0
- data/lib/tty/reader/win_api.rb +54 -0
- data/lib/tty/reader/win_console.rb +90 -0
- data/tasks/console.rake +11 -0
- data/tasks/coverage.rake +11 -0
- data/tasks/spec.rake +29 -0
- data/tty-reader.gemspec +28 -0
- metadata +137 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'io/console'
|
5
|
+
|
6
|
+
module TTY
|
7
|
+
class Reader
|
8
|
+
class Mode
|
9
|
+
# Initialize a Terminal
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
def initialize(input = $stdin)
|
13
|
+
@input = input
|
14
|
+
end
|
15
|
+
|
16
|
+
# Echo given block
|
17
|
+
#
|
18
|
+
# @param [Boolean] is_on
|
19
|
+
#
|
20
|
+
# @api public
|
21
|
+
def echo(is_on = true, &block)
|
22
|
+
if is_on || !@input.tty?
|
23
|
+
yield
|
24
|
+
else
|
25
|
+
@input.noecho(&block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Use raw mode in the given block
|
30
|
+
#
|
31
|
+
# @param [Boolean] is_on
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
def raw(is_on = true, &block)
|
35
|
+
if is_on && @input.tty?
|
36
|
+
@input.raw(&block)
|
37
|
+
else
|
38
|
+
yield
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end # Mode
|
42
|
+
end # Reader
|
43
|
+
end # TTY
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'fiddle'
|
5
|
+
|
6
|
+
module TTY
|
7
|
+
class Reader
|
8
|
+
module WinAPI
|
9
|
+
include Fiddle
|
10
|
+
|
11
|
+
Handle = RUBY_VERSION >= "2.0.0" ? Fiddle::Handle : DL::Handle
|
12
|
+
|
13
|
+
CRT_HANDLE = Handle.new("msvcrt") rescue Handle.new("crtdll")
|
14
|
+
|
15
|
+
# Get a character from the console without echo.
|
16
|
+
#
|
17
|
+
# @return [String]
|
18
|
+
# return the character read
|
19
|
+
#
|
20
|
+
# @api public
|
21
|
+
def getch
|
22
|
+
@@getch ||= Fiddle::Function.new(CRT_HANDLE["_getch"], [], TYPE_INT)
|
23
|
+
@@getch.call
|
24
|
+
end
|
25
|
+
module_function :getch
|
26
|
+
|
27
|
+
# Gets a character from the console with echo.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
# return the character read
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
def getche
|
34
|
+
@@getche ||= Fiddle::Function.new(CRT_HANDLE["_getche"], [], TYPE_INT)
|
35
|
+
@@getche.call
|
36
|
+
end
|
37
|
+
module_function :getche
|
38
|
+
|
39
|
+
# Check the console for recent keystroke. If the function
|
40
|
+
# returns a nonzero value, a keystroke is waiting in the buffer.
|
41
|
+
#
|
42
|
+
# @return [Integer]
|
43
|
+
# return a nonzero value if a key has been pressed. Otherwirse,
|
44
|
+
# it returns 0.
|
45
|
+
#
|
46
|
+
# @api public
|
47
|
+
def kbhit
|
48
|
+
@@kbhit ||= Fiddle::Function.new(CRT_HANDLE["_kbhit"], [], TYPE_INT)
|
49
|
+
@@kbhit.call
|
50
|
+
end
|
51
|
+
module_function :kbhit
|
52
|
+
end # WinAPI
|
53
|
+
end # Reader
|
54
|
+
end # TTY
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'codes'
|
5
|
+
|
6
|
+
module TTY
|
7
|
+
class Reader
|
8
|
+
class WinConsole
|
9
|
+
ESC = "\e".freeze
|
10
|
+
NUL_HEX = "\x00".freeze
|
11
|
+
EXT_HEX = "\xE0".freeze
|
12
|
+
|
13
|
+
# Key codes
|
14
|
+
#
|
15
|
+
# @return [Hash[Symbol]]
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
attr_reader :keys
|
19
|
+
|
20
|
+
# Escape codes
|
21
|
+
#
|
22
|
+
# @return [Array[Integer]]
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
attr_reader :escape_codes
|
26
|
+
|
27
|
+
def initialize(input)
|
28
|
+
require_relative 'win_api'
|
29
|
+
@input = input
|
30
|
+
@keys = Codes.win_keys
|
31
|
+
@escape_codes = [[NUL_HEX.ord], [ESC.ord], EXT_HEX.bytes.to_a]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Get a character from console blocking for input
|
35
|
+
#
|
36
|
+
# @param [Hash[Symbol]] options
|
37
|
+
# @option options [Symbol] :echo
|
38
|
+
# the echo mode toggle
|
39
|
+
# @option options [Symbol] :raw
|
40
|
+
# the raw mode toggle
|
41
|
+
#
|
42
|
+
# @return [String]
|
43
|
+
#
|
44
|
+
# @api private
|
45
|
+
def get_char(options)
|
46
|
+
if options[:raw] && options[:echo]
|
47
|
+
if options[:nonblock]
|
48
|
+
get_char_echo_non_blocking
|
49
|
+
else
|
50
|
+
get_char_echo_blocking
|
51
|
+
end
|
52
|
+
elsif options[:raw] && !options[:echo]
|
53
|
+
options[:nonblock] ? get_char_non_blocking : get_char_blocking
|
54
|
+
elsif !options[:raw] && !options[:echo]
|
55
|
+
options[:nonblock] ? get_char_non_blocking : get_char_blocking
|
56
|
+
else
|
57
|
+
@input.getc
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Get the char for last key pressed, or if no keypress return nil
|
62
|
+
#
|
63
|
+
# @api private
|
64
|
+
def get_char_non_blocking
|
65
|
+
input_ready? ? get_char_blocking : nil
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_char_echo_non_blocking
|
69
|
+
input_ready? ? get_char_echo_blocking : nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_char_blocking
|
73
|
+
WinAPI.getch.chr
|
74
|
+
end
|
75
|
+
|
76
|
+
def get_char_echo_blocking
|
77
|
+
WinAPI.getche.chr
|
78
|
+
end
|
79
|
+
|
80
|
+
# Check if IO has user input
|
81
|
+
#
|
82
|
+
# @return [Boolean]
|
83
|
+
#
|
84
|
+
# @api private
|
85
|
+
def input_ready?
|
86
|
+
!WinAPI.kbhit.zero?
|
87
|
+
end
|
88
|
+
end # Console
|
89
|
+
end # Reader
|
90
|
+
end # TTY
|
data/tasks/console.rake
ADDED
data/tasks/coverage.rake
ADDED
data/tasks/spec.rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
desc 'Run all specs'
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
8
|
+
task.pattern = 'spec/{unit,integration}{,/*/**}/*_spec.rb'
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :spec do
|
12
|
+
desc 'Run unit specs'
|
13
|
+
RSpec::Core::RakeTask.new(:unit) do |task|
|
14
|
+
task.pattern = 'spec/unit{,/*/**}/*_spec.rb'
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Run integration specs'
|
18
|
+
RSpec::Core::RakeTask.new(:integration) do |task|
|
19
|
+
task.pattern = 'spec/integration{,/*/**}/*_spec.rb'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
rescue LoadError
|
24
|
+
%w[spec spec:unit spec:integration].each do |name|
|
25
|
+
task name do
|
26
|
+
$stderr.puts "In order to run #{name}, do `gem install rspec`"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/tty-reader.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "tty/reader/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "tty-reader"
|
8
|
+
spec.version = TTY::Reader::VERSION
|
9
|
+
spec.authors = ["Piotr Murach"]
|
10
|
+
spec.email = [""]
|
11
|
+
spec.summary = %q{Provides a set of methods for processing keyboard input in character, line and multiline modes.}
|
12
|
+
spec.description = %q{Provides a set of methods for processing keyboard input in character, line and multiline modes. In addition it maintains history of entered input with an ability to recall and re-edit those inputs and register to listen for keystrokes.}
|
13
|
+
spec.homepage = "https://piotrmurach.github.io/tty"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "wisper", "~> 2.0.0"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", ">= 1.5.0", "< 2.0"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tty-reader
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Piotr Murach
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-08-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: wisper
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.5.0
|
34
|
+
- - "<"
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '2.0'
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.5.0
|
44
|
+
- - "<"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '2.0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rspec
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.0'
|
75
|
+
description: Provides a set of methods for processing keyboard input in character,
|
76
|
+
line and multiline modes. In addition it maintains history of entered input with
|
77
|
+
an ability to recall and re-edit those inputs and register to listen for keystrokes.
|
78
|
+
email:
|
79
|
+
- ''
|
80
|
+
executables: []
|
81
|
+
extensions: []
|
82
|
+
extra_rdoc_files: []
|
83
|
+
files:
|
84
|
+
- ".gitignore"
|
85
|
+
- ".rspec"
|
86
|
+
- ".travis.yml"
|
87
|
+
- CHANGELOG.md
|
88
|
+
- CODE_OF_CONDUCT.md
|
89
|
+
- Gemfile
|
90
|
+
- LICENSE.txt
|
91
|
+
- README.md
|
92
|
+
- Rakefile
|
93
|
+
- appveyor.yml
|
94
|
+
- bin/console
|
95
|
+
- bin/setup
|
96
|
+
- lib/tty-reader.rb
|
97
|
+
- lib/tty/reader.rb
|
98
|
+
- lib/tty/reader/codes.rb
|
99
|
+
- lib/tty/reader/console.rb
|
100
|
+
- lib/tty/reader/history.rb
|
101
|
+
- lib/tty/reader/key_event.rb
|
102
|
+
- lib/tty/reader/line.rb
|
103
|
+
- lib/tty/reader/mode.rb
|
104
|
+
- lib/tty/reader/version.rb
|
105
|
+
- lib/tty/reader/win_api.rb
|
106
|
+
- lib/tty/reader/win_console.rb
|
107
|
+
- tasks/console.rake
|
108
|
+
- tasks/coverage.rake
|
109
|
+
- tasks/spec.rake
|
110
|
+
- tty-reader.gemspec
|
111
|
+
homepage: https://piotrmurach.github.io/tty
|
112
|
+
licenses:
|
113
|
+
- MIT
|
114
|
+
metadata: {}
|
115
|
+
post_install_message:
|
116
|
+
rdoc_options: []
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 2.5.1
|
132
|
+
signing_key:
|
133
|
+
specification_version: 4
|
134
|
+
summary: Provides a set of methods for processing keyboard input in character, line
|
135
|
+
and multiline modes.
|
136
|
+
test_files: []
|
137
|
+
has_rdoc:
|