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.
@@ -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,7 @@
1
+ # encoding: utf-8
2
+
3
+ module TTY
4
+ class Reader
5
+ VERSION = "0.1.0"
6
+ end # Reader
7
+ 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
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ desc 'Load gem inside irb console'
4
+ task :console do
5
+ require 'irb'
6
+ require 'irb/completion'
7
+ require File.join(__FILE__, '../../lib/tty-reader')
8
+ ARGV.clear
9
+ IRB.start
10
+ end
11
+ task c: %w[ console ]
@@ -0,0 +1,11 @@
1
+ # encoding: utf-8
2
+
3
+ desc 'Measure code coverage'
4
+ task :coverage do
5
+ begin
6
+ original, ENV['COVERAGE'] = ENV['COVERAGE'], 'true'
7
+ Rake::Task['spec'].invoke
8
+ ensure
9
+ ENV['COVERAGE'] = original
10
+ end
11
+ end
@@ -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
@@ -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: