mini_term 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,176 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Test mapped sequences coming from the keyboard.
4
+ #
5
+
6
+ require_relative '../lib/mini_term'
7
+
8
+ MiniTerm.open
9
+ no_map = false
10
+ $mini_term_exit_info = {}
11
+
12
+ # Process any arguments.
13
+ ARGV.each do |arg|
14
+ if arg == '--no-map'
15
+ no_map = true
16
+ else
17
+ path = File.absolute_path(arg)
18
+ puts "Requiring '#{path}'"
19
+ require path
20
+ end
21
+ end
22
+
23
+ puts
24
+
25
+ # Load the sample Windows mapping.
26
+ unless MiniTerm.map_types.include?(:windows)
27
+ MiniTerm.add_map(:windows) do |map|
28
+
29
+ unless no_map
30
+
31
+ # Make local copies of the prefixes for brevity.
32
+ x00 = MiniTerm::PREFIX_00
33
+ xe0 = MiniTerm::PREFIX_E0
34
+
35
+ map[" ".."~"] = :insert_text
36
+
37
+ #Left Arrows
38
+ map[x00+"K"] = :go_left
39
+ map[xe0+"K"] = :go_left
40
+
41
+ map[x00+"s"] = :word_left
42
+ map[xe0+"s"] = :word_left
43
+
44
+ #Right Arrows
45
+ map[x00+"M"] = :go_right
46
+ map[xe0+"M"] = :go_right
47
+
48
+ map[x00+"t"] = :word_right
49
+ map[xe0+"t"] = :word_right
50
+
51
+ #Up Arrows
52
+ map[x00+"H"] = :previous_history
53
+ map[xe0+"H"] = :previous_history
54
+
55
+ #Down Arrows
56
+ map[x00+"P"] = :next_history
57
+ map[xe0+"P"] = :next_history
58
+
59
+ #The Home keys
60
+ map[x00+"G"] = :go_home
61
+ map[xe0+"G"] = :go_home
62
+
63
+ #The End keys
64
+ map[x00+"O"] = :go_end
65
+ map[xe0+"O"] = :go_end
66
+
67
+ #The Backspace key
68
+ map["\x08"] = :delete_left
69
+
70
+ #The Delete keys
71
+ map["\x7F"] = :delete_right
72
+ map[x00+"S"] = :delete_right
73
+ map[xe0+"S"] = :delete_right
74
+
75
+ #Auto-completion.
76
+ map["\t"] = :auto_complete
77
+
78
+ #The Enter key
79
+ map["\x0D"] = :enter
80
+
81
+ #The Escape key
82
+ map["\e"] = :cancel
83
+ end
84
+
85
+ #End of Input
86
+ map["\x1A"] = :end_of_input
87
+
88
+ $mini_term_exit_info[:windows] = [:end_of_input, "Ctrl+z"]
89
+ end
90
+ end
91
+
92
+ # Load the sample ANSI mapping.
93
+ unless MiniTerm.map_types.include?(:ansi)
94
+ MiniTerm.add_map(:ansi) do |map|
95
+
96
+ unless no_map
97
+ map[" ".."~"] = :insert_text
98
+
99
+ #Left Arrows
100
+ map["\e[D"] = :go_left
101
+ map["\eOD"] = :go_left
102
+ map["\x02"] = :go_left
103
+
104
+ map["\e[1;5D"] = :word_left
105
+ map["\eb"] = :word_left
106
+
107
+ #Right Arrows
108
+ map["\e[C"] = :go_right
109
+ map["\eOC"] = :go_right
110
+ map["\x06"] = :go_right
111
+
112
+ map["\e[1;5C"] = :word_right
113
+ map["\ef"] = :word_right
114
+
115
+ #Up Arrows
116
+ map["\e[A"] = :previous_history
117
+ map["\eOA"] = :previous_history
118
+ map["\x12"] = :previous_history
119
+
120
+ #Down Arrows
121
+ map["\e[B"] = :next_history
122
+ map["\eOB"] = :next_history
123
+
124
+ #The Home keys
125
+ map["\e[H"] = :go_home
126
+ map["\eOH"] = :go_home
127
+ map["\x01"] = :go_home
128
+
129
+ #The End keys
130
+ map["\e[F"] = :go_end
131
+ map["\eOF"] = :go_end
132
+ map["\x05"] = :go_end
133
+
134
+ #The Backspace key
135
+ map["\x7F"] = :delete_left
136
+ map["\x08"] = :delete_left
137
+ map["\x15"] = :delete_all_left
138
+
139
+ #The Delete keys
140
+ map["\x1F"] = :delete_right
141
+ map["\e[3~"] = :delete_right
142
+ map["\x0B"] = :delete_all_right
143
+
144
+ #Auto-completion.
145
+ map["\t"] = :auto_complete
146
+
147
+ #The Enter key
148
+ map["\x0D"] = :enter
149
+
150
+ #The Cancel key
151
+ map["\f"] = :cancel
152
+ end
153
+
154
+ #End of Input
155
+ map["\ez"] = :end_of_input
156
+
157
+ $mini_term_exit_info[:ansi] = [:end_of_input, "Alt+z"]
158
+ end
159
+ end
160
+
161
+ exit_action, exit_desc = $mini_term_exit_info[MiniTerm::TERM_TYPE]
162
+ puts "Testing Mapped Keyboard input. Press #{exit_desc} to quit."
163
+
164
+ puts "Current maps = #{MiniTerm.map_types.inspect}"
165
+ puts "Current term type = #{MiniTerm::TERM_TYPE.inspect}"
166
+ puts
167
+
168
+ loop do
169
+ mapped = MiniTerm.get_mapped_char
170
+ puts "action = #{mapped[0].inspect}, text = #{mapped[1].chars.inspect}"
171
+ break if mapped[0] == exit_action
172
+ end
173
+
174
+ MiniTerm.close
175
+ puts
176
+ puts
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # It's snowing!
4
+ #
5
+
6
+ require_relative '../lib/mini_term'
7
+
8
+ begin
9
+ MiniTerm.open
10
+
11
+ if ARGV[0]
12
+ start = ARGV[0].hex
13
+
14
+ if ARGV[1]
15
+ finish = ARGV[1].hex
16
+ snow_flakes = (start..finish).map {|c| c.chr(Encoding::UTF_8)}
17
+ else
18
+ snow_flakes = [start.chr(Encoding::UTF_8)]
19
+ end
20
+
21
+ else
22
+ snow_flakes = ["*"]
23
+ end
24
+
25
+ gen = Random.new
26
+
27
+ y_limit, x_limit = MiniTerm.term_info
28
+
29
+ loop do
30
+ x = gen.rand(x_limit)
31
+ y = gen.rand(y_limit)
32
+
33
+ if (x < (x_limit-1)) || (y < (y_limit-1))
34
+ MiniTerm.set_posn(row: y, column: x)
35
+ snow_flakes.shuffle!
36
+ MiniTerm.print(snow_flakes[0])
37
+ end
38
+
39
+ x = gen.rand(x_limit)
40
+ y = gen.rand(y_limit)
41
+
42
+ if (x < (x_limit-1)) || (y < (y_limit-1))
43
+ MiniTerm.set_posn(row: y, column: x)
44
+ MiniTerm.print(" ")
45
+ end
46
+
47
+ break if MiniTerm.raw(&:has_raw_char?)
48
+ end
49
+
50
+ ensure
51
+ MiniTerm.getch
52
+ MiniTerm.clear_screen
53
+ MiniTerm.close
54
+ end
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Sample the first 65536 code points.
4
+ #
5
+
6
+ # Compute the range of code points to be displayed.
7
+ last_code, first_code = ARGV.map(&:hex).reverse
8
+ first_code ||= 32
9
+ last_code ||= 65536
10
+ last_code = 65536 if last_code > 65536
11
+
12
+ puts "Code points in the range: #{"%X"%first_code}...#{"%X"%last_code}"
13
+
14
+ # Compute the 64 element lines to be displayed.
15
+ first_line = first_code/64
16
+ last_line = (last_code+63)/64
17
+
18
+ # Display the code points.
19
+ (first_line...last_line).each do |line|
20
+ print "%4X " % (line*64)
21
+
22
+ 8.times do |bundle|
23
+ print ' '
24
+ start = line*64 + bundle*8
25
+ finish = start+8
26
+
27
+ (start...finish).each do |code|
28
+ if code.between?(first_code, last_code) && code >= 32
29
+ begin
30
+ print code.chr(Encoding::UTF_8)
31
+ rescue RangeError
32
+ print 'E'
33
+ end
34
+ else
35
+ print ' '
36
+ end
37
+
38
+ end
39
+ end
40
+
41
+ puts
42
+ end
data/exe/raw_key_test ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Test raw byte sequences coming from the keyboard.
4
+ #
5
+
6
+ require_relative '../lib/mini_term'
7
+
8
+ puts "Testing Raw Keyboard input. Press Q to quit."
9
+ MiniTerm.open(pass_ctrl_s: true, pass_ctrl_c: true)
10
+ key = nil
11
+
12
+ MiniTerm.raw do |i|
13
+ until key == "Q"
14
+ key = MiniTerm.get_raw_char
15
+ print "[" + "%02X" % key.bytes[0] + "]"
16
+ end
17
+ end
18
+
19
+ MiniTerm.close
20
+ puts
21
+ puts
data/irbt.rb ADDED
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+ # An IRB + mini_term test session.
3
+
4
+ require 'irb'
5
+
6
+ puts "Starting an IRB console with mini_term loaded."
7
+
8
+ if ARGV[0] == 'local'
9
+ require_relative 'lib/mini_term'
10
+ puts "mini_term loaded locally: #{MiniTerm::VERSION}"
11
+
12
+ ARGV.shift
13
+ else
14
+ require 'mini_term'
15
+ puts "mini_term loaded from gem: #{MiniTerm::VERSION}"
16
+ end
17
+
18
+ IRB.start
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+
3
+ # MiniTerm needs to put text on the screen! (ANSI 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
+ # Sound a beep
13
+ def self.beep
14
+ STDERR.write(BELL)
15
+ STDERR.flush
16
+ self
17
+ end
18
+
19
+ # Clear the screen and home the cursor
20
+ def self.clear_screen
21
+ STDOUT.print("\e[f\e[2J")
22
+ self
23
+ end
24
+
25
+ end
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+
3
+ # Get input from the user in raw mode. (ANSI Specific Code)
4
+ module MiniTerm
5
+
6
+ # Is there a character waiting?
7
+ def self.has_raw_char?
8
+ raw { STDIN.ready? }
9
+ end
10
+
11
+ #Get a uncooked character keystroke.
12
+ def self.get_raw_char
13
+ fail MiniTermNotRaw, "Not in raw mode." unless raw?
14
+ STDIN.getch
15
+ end
16
+
17
+ private
18
+
19
+ # Get user input uncooked, with no echo or buffering.
20
+ def self.begin_raw_input
21
+ @raw_input = true
22
+ STDIN.raw!
23
+ end
24
+
25
+ # Done with raw mode for now.
26
+ def self.end_raw_input
27
+ STDIN.cooked!
28
+ @raw_input = false
29
+ end
30
+
31
+ end
@@ -0,0 +1,17 @@
1
+ # coding: utf-8
2
+
3
+ # Give MiniTerm control of the cursor position. (ANSI Specific Code)
4
+ module MiniTerm
5
+
6
+ # Set the row (optional) and column of the cursor.
7
+ def self.set_posn(row: nil, column:)
8
+ if row
9
+ STDOUT.print("\e[#{row};#{column}f")
10
+ else
11
+ STDOUT.print("\e#{column}G")
12
+ end
13
+
14
+ self
15
+ end
16
+
17
+ end
@@ -0,0 +1,11 @@
1
+ # coding: utf-8
2
+
3
+ # Get size info about the console window. (ANSI Specific Code)
4
+ module MiniTerm
5
+
6
+ # Get term_info [rows, cols]
7
+ def self.term_info
8
+ IO.console.winsize
9
+ end
10
+
11
+ end
@@ -0,0 +1,16 @@
1
+ # coding: utf-8
2
+
3
+ require 'io/console'
4
+ require 'io/wait'
5
+
6
+ require_relative 'ansi/term_info'
7
+ require_relative 'ansi/set_posn'
8
+ require_relative 'ansi/raw_input'
9
+ require_relative 'ansi/output'
10
+
11
+ module MiniTerm
12
+
13
+ # What options are supported in this ANSI mode?
14
+ VALID_OPTIONS = [:quiet, :strict].freeze
15
+
16
+ end
@@ -0,0 +1,15 @@
1
+ # coding: utf-8
2
+
3
+ # Common control character definitions. (Common Code)
4
+ module MiniTerm
5
+
6
+ BELL = "\x07"
7
+ LINE_FEED = "\x0A"
8
+ CARRIAGE_RETURN = "\x0D"
9
+ ESCAPE = "\x1B"
10
+
11
+ # These are mostly used in Windows maps.
12
+ PREFIX_00 = 0x00.chr
13
+ PREFIX_E0 = 0xE0.chr
14
+
15
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+
3
+ # Get input from the user in mapped mode. (Common Code)
4
+ module MiniTerm
5
+
6
+ # The different keyboard maps available.
7
+ @maps = Hash.new do |_h, key|
8
+ fail MiniTermNoMap, "No mapping for term type #{key.inspect}."
9
+ end
10
+
11
+ # What terminal types are mapped?
12
+ def self.map_types
13
+ @maps.keys
14
+ end
15
+
16
+ # Add a terminal mapping.
17
+ def self.add_map(type, &defn_block)
18
+ @maps[type] = Mapper.new(&defn_block)
19
+ end
20
+
21
+ # Get a mapped character. Note: The block is for testing only.
22
+ def self.get_mapped_char(&block)
23
+ mapper = @maps[MiniTerm::TERM_TYPE]
24
+ proc = block_given? ? block : Proc.new { get_raw_char }
25
+ raw { mapper.get_mapped_char(&proc) }
26
+ end
27
+
28
+ end
@@ -0,0 +1,58 @@
1
+ # coding: utf-8
2
+
3
+ # A input text mapper. (Common Code)
4
+ module MiniTerm
5
+
6
+ # Translate raw input to mapped commands.
7
+ class Mapper
8
+
9
+ #Set up the keystroke mapper.
10
+ def initialize
11
+ @map = Hash.new {|_h, key| [:unmapped, key]}
12
+ yield self
13
+ end
14
+
15
+ #Add a map entry
16
+ def []=(indexes, value)
17
+ indexes = [indexes] unless indexes.is_a?(Range)
18
+
19
+ indexes.each do |index|
20
+ process_non_terminals(index)
21
+
22
+ if @map.has_key?(index)
23
+ fail MiniTermKME, "Duplicate entry #{index.inspect}"
24
+ end
25
+
26
+ @map[index] = [value, index]
27
+ end
28
+ end
29
+
30
+ #Handle the preamble characters in the command sequence.
31
+ def process_non_terminals(index)
32
+ seq = ""
33
+
34
+ index.chop.chars.each do |char|
35
+ seq << char
36
+
37
+ if @map.has_key?(seq) && @map[seq]
38
+ fail MiniTermKME, "Ambiguous entry #{index.inspect}"
39
+ end
40
+
41
+ @map[seq] = false
42
+ end
43
+ end
44
+
45
+ #Get a mapped input sequence.
46
+ def get_mapped_char
47
+ key_seq, key_cmd = "", nil
48
+
49
+ begin
50
+ key_seq << yield
51
+ key_cmd = @map[key_seq]
52
+ end until key_cmd
53
+
54
+ key_cmd
55
+ end
56
+ end
57
+
58
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+
3
+ # Get input from the user in raw mode. (Common Code)
4
+ module MiniTerm
5
+
6
+ # Is input raw or cooked?
7
+ @raw_input = false
8
+
9
+ # Is raw mode in effect?
10
+ def self.raw?
11
+ @raw_input
12
+ end
13
+
14
+ # Execute the block with input in raw mode.
15
+ def self.raw
16
+ begin_raw_input unless (already_raw = raw?)
17
+ yield(self)
18
+ ensure
19
+ end_raw_input unless already_raw
20
+ end
21
+
22
+ # Flush the keyboard buffer.
23
+ def self.flush
24
+ raw do |input|
25
+ while input.has_raw_char?
26
+ input.get_raw_char
27
+ end
28
+ end
29
+
30
+ self
31
+ end
32
+
33
+ end
@@ -0,0 +1,54 @@
1
+ # coding: utf-8
2
+
3
+ # Common Terminal Info. (Common Code)
4
+ module MiniTerm
5
+
6
+ @options = nil
7
+ @term_open = false
8
+
9
+ def self.open(options = {})
10
+ @term_open = true
11
+ @options = options
12
+ validate_options
13
+ end
14
+
15
+ def self.close
16
+ end_raw_input if raw?
17
+ @term_open = false
18
+ @options = nil
19
+ end
20
+
21
+ # Is the mini_term open just now?
22
+ def self.term_open?
23
+ @term_open
24
+ end
25
+
26
+ # Make sure that mini_term is closed on exit.
27
+ at_exit do
28
+ if MiniTerm.term_open?
29
+ puts "Force MiniTerm.close" unless @options[:quiet]
30
+ MiniTerm.close
31
+ end
32
+ end
33
+
34
+ # What is the terminal width in characters?
35
+ def self.width
36
+ term_info[1]
37
+ end
38
+
39
+ # What is the terminal height in rows?
40
+ def self.height
41
+ term_info[0]
42
+ end
43
+
44
+ private
45
+
46
+ def self.validate_options
47
+ return if (bad = @options.keys - VALID_OPTIONS).empty?
48
+
49
+ msg = "MiniTerm.open, Invalid options: #{bad.join(", ")}"
50
+ puts msg unless @options[:quiet]
51
+ fail MiniTermStrict, msg if @options[:strict]
52
+ end
53
+
54
+ end
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ # The abstract base exception for mini term.
4
+ class MiniTermError < StandardError; end
5
+
6
+ # The exception raised when something is really messed up.
7
+ class MiniTermWTF < MiniTermError; end
8
+
9
+ # The exception raised due to strictness.
10
+ class MiniTermStrict < MiniTermError; end
11
+
12
+ # The exception raised when no keyboard mapping is found.
13
+ class MiniTermNoMap < MiniTermError; end
14
+
15
+ # The exception raised when the keyboard mapping is invalid.
16
+ class MiniTermKME < MiniTermError; end
17
+
18
+ # The exception raised when raw mode is mandatory.
19
+ class MiniTermNotRaw < MiniTermError; end
@@ -0,0 +1,8 @@
1
+ # coding: utf-8
2
+
3
+ # A simple, portable terminal interface object.
4
+ module MiniTerm
5
+ VERSION = "0.1.0".freeze
6
+
7
+ DESCRIPTION = "mini_term: A portable encapsulation of the console terminal.".freeze
8
+ end