mini_term 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
1
+ # coding: utf-8
2
+
3
+ # Link Ruby to the Windows API calls needed by MiniTerm
4
+ module MiniTerm
5
+
6
+ # The magic numbers for the handles.
7
+ STDIN_ID = -10
8
+ STDOUT_ID = -11
9
+
10
+ # MiniTerm needs to retrieve standard handles.
11
+ get_handle_proc = Win32API.new("kernel32", "GetStdHandle", ['L'], 'L')
12
+
13
+ define_singleton_method(:get_handle) do |handle_index|
14
+ get_handle_proc.call(handle_index)
15
+ end
16
+
17
+ # Well, stdout's handle in particular.
18
+ def self.stdout_handle
19
+ get_handle(STDOUT_ID)
20
+ end
21
+
22
+ # Well, stdin's handle in particular.
23
+ def self.stdin_handle
24
+ get_handle(STDIN_ID)
25
+ end
26
+
27
+ # MiniTerm needs to get the current stdin mode
28
+ get_mode_proc = Win32API.new("kernel32", "GetConsoleMode", ['L', 'P'], 'I')
29
+
30
+ define_singleton_method(:get_console_mode) do |buffer|
31
+ get_mode_proc.call(stdin_handle, buffer)
32
+ end
33
+
34
+ # MiniTerm needs to set the current stdin mode
35
+ set_mode_proc = Win32API.new("kernel32", "SetConsoleMode", ['L', 'L'], 'I')
36
+
37
+ define_singleton_method(:set_console_mode) do |new_mode|
38
+ set_mode_proc.call(stdin_handle, new_mode)
39
+ end
40
+
41
+ # MiniTerm needs to retrieve screen info.
42
+ get_screen_info_proc = Win32API.new("kernel32",
43
+ "GetConsoleScreenBufferInfo",
44
+ ['L','P'], 'L')
45
+
46
+ define_singleton_method(:get_screen_info) do |buffer|
47
+ get_screen_info_proc.call(stdout_handle, buffer)
48
+ end
49
+
50
+ # MiniTerm needs to move the cursor about.
51
+ set_cursor_posn_proc = Win32API.new("kernel32",
52
+ "SetConsoleCursorPosition",
53
+ ['L','L'], 'L')
54
+
55
+ define_singleton_method(:set_cursor_posn) do |position|
56
+ set_cursor_posn_proc.call(stdout_handle, position)
57
+ end
58
+
59
+ # MiniTerm needs to know if any keystrokes are waiting.
60
+ getch_proc = Win32API.new("msvcrt", "_getch", [], 'I')
61
+ define_singleton_method(:getch) { getch_proc.call.chr }
62
+
63
+ # MiniTerm needs to get a single character in raw mode.
64
+ kbhit_proc = Win32API.new("msvcrt", "_kbhit", [], 'I')
65
+ define_singleton_method(:kbhit) { kbhit_proc.call }
66
+
67
+ # MiniTerm needs to make some noise.
68
+ beep_proc = Win32API.new("user32", "MessageBeep", ['L'], '0')
69
+ define_singleton_method(:beep) { beep_proc.call(0); self }
70
+
71
+ end
@@ -0,0 +1,20 @@
1
+ # coding: utf-8
2
+
3
+ # MiniTerm needs to put text on the screen! (Windows Specific Code)
4
+ module MiniTerm
5
+
6
+ # Put some text onto the screen.
7
+ def self.print(text)
8
+ STDOUT.print(text)
9
+ self
10
+ end
11
+
12
+ # See link.rb for the beep method.
13
+
14
+ # Clear the screen and home the cursor
15
+ def self.clear_screen
16
+ system("cls")
17
+ self
18
+ end
19
+
20
+ end
@@ -0,0 +1,50 @@
1
+ # coding: utf-8
2
+
3
+ # Get input from the user in raw mode. (Windows Specific Code)
4
+ module MiniTerm
5
+
6
+ # The sleep interval waiting for a key to be pressed.
7
+ WAIT_SLEEP = 0.02
8
+ TERM_MODE_MASK = 0xFFFFFFFF
9
+ ENABLE_LINE_INPUT = 0x00000002
10
+ ENABLE_PROCESSED_INPUT = 0x00000001
11
+
12
+ # Is there a character waiting?
13
+ def self.has_raw_char?
14
+ raw { kbhit != 0 }
15
+ end
16
+
17
+ # Get a uncooked character keystroke.
18
+ def self.get_raw_char
19
+ fail MiniTermNotRaw, "Not in raw mode." unless raw?
20
+
21
+ while (kbhit == 0)
22
+ sleep(WAIT_SLEEP)
23
+ end
24
+
25
+ getch
26
+ end
27
+
28
+ private
29
+
30
+ # Get user input uncooked, with no echo or buffering.
31
+ def self.begin_raw_input
32
+ @saved_mode = get_term_mode
33
+
34
+ mask = TERM_MODE_MASK ^
35
+ (@options[:pass_ctrl_s] ? ENABLE_LINE_INPUT : 0) ^
36
+ (@options[:pass_ctrl_c] ? ENABLE_PROCESSED_INPUT : 0)
37
+
38
+ # Clear the ENABLE_LINE_INPUT and ENABLE_PROCESSED_INPUT flags.
39
+ # See https://docs.microsoft.com/en-us/windows/console/setconsolemode
40
+ set_term_mode(@saved_mode & mask)
41
+ @raw_input = true
42
+ end
43
+
44
+ # Done with raw mode for now.
45
+ def self.end_raw_input
46
+ set_term_mode(@saved_mode)
47
+ @raw_input = false
48
+ end
49
+
50
+ end
@@ -0,0 +1,12 @@
1
+ # coding: utf-8
2
+
3
+ # Give MiniTerm control of the cursor position. (Windows Specific Code)
4
+ module MiniTerm
5
+
6
+ # Set the row (optional) and column of the cursor.
7
+ def self.set_posn(row: get_cursor_row, column:)
8
+ set_cursor_posn(row * 65536 + column)
9
+ self
10
+ end
11
+
12
+ end
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+
3
+ # Get size info about the console window. (Windows Specific Code)
4
+ module MiniTerm
5
+
6
+ # Get term_info [rows, cols]
7
+ def self.term_info
8
+ raw_buffer = 0.chr * 24
9
+ get_screen_info(raw_buffer)
10
+
11
+ width = (raw_buffer[0,2].unpack('S'))[0]
12
+ _left, top, _right, bottom = raw_buffer[10,8].unpack('SSSS')
13
+
14
+ [bottom - top + 1, width]
15
+ end
16
+
17
+ private
18
+
19
+ # Get the current terminal mode.
20
+ def self.get_term_mode
21
+ raw_buffer = 0.chr * 8
22
+ get_console_mode(raw_buffer)
23
+ raw_buffer[0,4].unpack('L')[0]
24
+ end
25
+
26
+ # Get the current terminal mode.
27
+ def self.set_term_mode(new_mode)
28
+ set_console_mode(new_mode)
29
+ end
30
+
31
+ # Get the current row of the cursor.
32
+ def self.get_cursor_row
33
+ raw_buffer = 0.chr * 24
34
+ get_screen_info(raw_buffer)
35
+ (raw_buffer[6,2].unpack('S'))[0]
36
+ end
37
+
38
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+
3
+ # Replacement support for deprecated win_32_api gem, with thanks to the
4
+ # ConnorAtherton/rb-readline project from where this code originates.
5
+ module MiniTerm
6
+
7
+ require 'fiddle'
8
+
9
+ #The classic Win32API gem is deprecated, so we emulate it with fiddle.
10
+ class Win32API
11
+ DLL = {}
12
+ TYPES = {"0" => Fiddle::TYPE_VOID,
13
+ "S" => Fiddle::TYPE_VOIDP,
14
+ "I" => Fiddle::TYPE_LONG}
15
+
16
+ def initialize(dll_name, func, import, export = "0", _ct = nil)
17
+ @proto = import.join.tr("VPpNnLlIi", "0SSI").chomp('0').split('')
18
+ handle = DLL[dll_name] ||= Fiddle.dlopen(dll_name)
19
+ @func = Fiddle::Function.new(handle[func], TYPES.values_at(*@proto), 1)
20
+ end
21
+
22
+ def call(*args)
23
+ args.each_with_index do |x, i|
24
+ if @proto[i] == "S"
25
+ args[i] = [x == 0 ? nil : x].pack("p").unpack("l!*")[0]
26
+ end
27
+ end
28
+
29
+ @func.call(*args).to_i
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+
3
+ # Get appropriate access to Windows API calls
4
+ if MiniTerm.java?
5
+ require 'win32api'
6
+ else
7
+ require_relative 'windows/win_32_api'
8
+ end
9
+
10
+ require_relative 'windows/link'
11
+ require_relative 'windows/term_info'
12
+ require_relative 'windows/set_posn'
13
+ require_relative 'windows/raw_input'
14
+ require_relative 'windows/output'
15
+
16
+ module MiniTerm
17
+
18
+ # What options are supported in this Windows?
19
+ VALID_OPTIONS = [:quiet, :strict, :pass_ctrl_s, :pass_ctrl_c].freeze
20
+
21
+ end
data/lib/mini_term.rb ADDED
@@ -0,0 +1,62 @@
1
+ # coding: utf-8
2
+
3
+ require 'rbconfig'
4
+
5
+ require_relative "mini_term/common/char_defs"
6
+ require_relative "mini_term/common/term_info"
7
+ require_relative "mini_term/common/raw_input"
8
+ require_relative "mini_term/common/mapper"
9
+ require_relative "mini_term/common/mapped_input"
10
+ require_relative "mini_term/version"
11
+
12
+ # A simple, portable terminal interface object. (Common Code)
13
+ module MiniTerm
14
+ host_os = RbConfig::CONFIG['host_os']
15
+
16
+ #What operating platform is in effect?
17
+ TERM_PLATFORM =
18
+ case host_os
19
+ when /mswin|msys|mingw|bccwin|wince|emc/
20
+ :windows
21
+ when /cygwin/
22
+ :cygwin
23
+ when /darwin|mac os/
24
+ :macosx
25
+ when /linux/
26
+ :linux
27
+ when /solaris|bsd/
28
+ :unix
29
+ else
30
+ raise "Unknown os: #{host_os.inspect}"
31
+ end
32
+
33
+ TERM_TYPE = (TERM_PLATFORM == :windows) ? :windows : :ansi
34
+
35
+ #Is Java present in the environment?
36
+ TERM_JAVA = (RUBY_PLATFORM =~ /java/) ? true : false
37
+
38
+ # Is this Windows?
39
+ def self.windows?
40
+ TERM_TYPE == :windows
41
+ end
42
+
43
+ # Is this ANSI?
44
+ def self.ansi?
45
+ TERM_TYPE == :ansi
46
+ end
47
+
48
+ # Are we running under Java?
49
+ def self.java?
50
+ TERM_JAVA
51
+ end
52
+ end
53
+
54
+ # Load in the appropriate code.
55
+ if MiniTerm.windows?
56
+ require_relative 'mini_term/windows'
57
+ elsif MiniTerm.ansi?
58
+ require_relative 'mini_term/ansi'
59
+ else
60
+ # This should never happen unless incorrect changes are made.
61
+ fail MiniTermWTF, "Invalid terminal type: #{MiniTerm::TERM_TYPE.inspect}"
62
+ end
data/mini_term.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "mini_term/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mini_term"
8
+ spec.version = MiniTerm::VERSION
9
+ spec.authors = ["PeterCamilleri"]
10
+ spec.email = ["peter.c.camilleri@gmail.com"]
11
+ spec.homepage = "https://github.com/PeterCamilleri/mini_term"
12
+
13
+ spec.summary = %q{A portable encapsulation of the console terminal.}
14
+ spec.description = %q{A portable encapsulation of the console terminal. } +
15
+ %q{Supports Linux, Mac, Windows, and Cygwin. }
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
19
+ f.match(%r{^(test|docs)/})
20
+ end
21
+
22
+ spec.require_paths = ["lib"]
23
+ spec.bindir = "exe"
24
+ spec.executables = spec
25
+ .files
26
+ .reject { |f| f.downcase == 'exe/readme.md'}
27
+ .grep(%r{^exe/}) { |f| File.basename(f) }
28
+
29
+ spec.required_ruby_version = '>=2.0'
30
+
31
+ spec.add_development_dependency "bundler", "~> 1.15"
32
+ spec.add_development_dependency "rake", "~> 10.0"
33
+ spec.add_development_dependency "minitest", "~> 5.0"
34
+ spec.add_development_dependency 'minitest_visible', "~> 0.1"
35
+ spec.add_development_dependency 'reek', "~> 5.0.2"
36
+ end
data/rakefile.rb ADDED
@@ -0,0 +1,41 @@
1
+ # coding: utf-8
2
+ require 'rake/testtask'
3
+ require "bundler/gem_tasks"
4
+
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << "test"
7
+ t.libs << "lib"
8
+ t.test_files = FileList["test/**/*_test.rb"]
9
+ end
10
+
11
+ task :default => :test
12
+
13
+ desc "Run a scan for smelly code!"
14
+ task :reek do |t|
15
+ `reek --no-color lib > reek.txt`
16
+ end
17
+
18
+ desc "Fire up an IRB session with mini_term preloaded."
19
+ task :console do
20
+ system "ruby irbt.rb local"
21
+ end
22
+
23
+ desc "What version of mini_term is this?"
24
+ task :vers do |t|
25
+ puts
26
+ puts "mini_term version = #{MiniTerm::VERSION}"
27
+ end
28
+
29
+ desc "Alternative test procedure"
30
+ task :alt_test, :target do |t, args|
31
+ args.with_defaults(:target => 'test')
32
+ here = File.dirname(__FILE__)
33
+ target = "#{here}/#{args[:target]}/*.rb"
34
+ puts "Target files = #{target}"
35
+ puts
36
+
37
+ block = "{|file| require file if File.basename(file) =~ /test/}"
38
+ code = "Dir['#{target}'].each #{block}"
39
+
40
+ system "ruby -e\"#{code}\""
41
+ end
@@ -0,0 +1,30 @@
1
+ # A sample test map for use with the mapped_key_test program.
2
+ # These demonstrate overriding the mappings built into the program.
3
+
4
+ $mini_term_exit_info = {}
5
+
6
+ MiniTerm.add_map(:windows) do |map|
7
+
8
+ # Make local copies of the prefixes for brevity.
9
+ x00 = MiniTerm::PREFIX_00
10
+ xe0 = MiniTerm::PREFIX_E0
11
+
12
+ #The Cancel key
13
+ map["\e"] = :cancel
14
+
15
+ #End of Input
16
+ map["\x1A"] = :end_of_input
17
+
18
+ $mini_term_exit_info[:windows] = [:end_of_input, "Ctrl+z"]
19
+ end
20
+
21
+ MiniTerm.add_map(:ansi) do |map|
22
+
23
+ #The Cancel key
24
+ map["\f"] = :cancel
25
+
26
+ #End of Input
27
+ map["\ez"] = :end_of_input
28
+
29
+ $mini_term_exit_info[:ansi] = [:end_of_input, "Alt+z"]
30
+ end
metadata ADDED
@@ -0,0 +1,153 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mini_term
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - PeterCamilleri
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-11-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.15'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.15'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest_visible
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: reek
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 5.0.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 5.0.2
83
+ description: 'A portable encapsulation of the console terminal. Supports Linux, Mac,
84
+ Windows, and Cygwin. '
85
+ email:
86
+ - peter.c.camilleri@gmail.com
87
+ executables:
88
+ - mapped_key_test
89
+ - mini_term_blizzard
90
+ - mini_term_code_points
91
+ - raw_key_test
92
+ extensions: []
93
+ extra_rdoc_files: []
94
+ files:
95
+ - ".gitignore"
96
+ - CODE_OF_CONDUCT.md
97
+ - Gemfile
98
+ - LICENSE.txt
99
+ - README.md
100
+ - exe/README.md
101
+ - exe/mapped_key_test
102
+ - exe/mini_term_blizzard
103
+ - exe/mini_term_code_points
104
+ - exe/raw_key_test
105
+ - irbt.rb
106
+ - lib/mini_term.rb
107
+ - lib/mini_term/ansi.rb
108
+ - lib/mini_term/ansi/output.rb
109
+ - lib/mini_term/ansi/raw_input.rb
110
+ - lib/mini_term/ansi/set_posn.rb
111
+ - lib/mini_term/ansi/term_info.rb
112
+ - lib/mini_term/common/char_defs.rb
113
+ - lib/mini_term/common/mapped_input.rb
114
+ - lib/mini_term/common/mapper.rb
115
+ - lib/mini_term/common/raw_input.rb
116
+ - lib/mini_term/common/term_info.rb
117
+ - lib/mini_term/exceptions.rb
118
+ - lib/mini_term/version.rb
119
+ - lib/mini_term/windows.rb
120
+ - lib/mini_term/windows/link.rb
121
+ - lib/mini_term/windows/output.rb
122
+ - lib/mini_term/windows/raw_input.rb
123
+ - lib/mini_term/windows/set_posn.rb
124
+ - lib/mini_term/windows/term_info.rb
125
+ - lib/mini_term/windows/win_32_api.rb
126
+ - mini_term.gemspec
127
+ - rakefile.rb
128
+ - samples/test_map.rb
129
+ homepage: https://github.com/PeterCamilleri/mini_term
130
+ licenses:
131
+ - MIT
132
+ metadata: {}
133
+ post_install_message:
134
+ rdoc_options: []
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '2.0'
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ requirements: []
148
+ rubyforge_project:
149
+ rubygems_version: 2.5.2
150
+ signing_key:
151
+ specification_version: 4
152
+ summary: A portable encapsulation of the console terminal.
153
+ test_files: []