tty-prompt 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +9 -6
- data/CHANGELOG.md +40 -3
- data/Gemfile +0 -1
- data/README.md +246 -65
- data/examples/ask.rb +7 -0
- data/examples/echo.rb +7 -0
- data/examples/in.rb +7 -0
- data/examples/mask.rb +9 -0
- data/examples/multi_select.rb +8 -0
- data/examples/select.rb +8 -0
- data/examples/validation.rb +9 -0
- data/examples/yes_no.rb +7 -0
- data/lib/tty-prompt.rb +6 -4
- data/lib/tty/prompt.rb +100 -25
- data/lib/tty/prompt/choice.rb +1 -1
- data/lib/tty/prompt/converter_dsl.rb +19 -0
- data/lib/tty/prompt/converter_registry.rb +56 -0
- data/lib/tty/prompt/converters.rb +77 -0
- data/lib/tty/prompt/evaluator.rb +29 -0
- data/lib/tty/prompt/list.rb +38 -36
- data/lib/tty/prompt/mask_question.rb +85 -0
- data/lib/tty/prompt/multi_list.rb +21 -32
- data/lib/tty/prompt/question.rb +184 -162
- data/lib/tty/prompt/question/checks.rb +85 -0
- data/lib/tty/prompt/question/modifier.rb +4 -5
- data/lib/tty/prompt/question/validation.rb +29 -35
- data/lib/tty/prompt/reader.rb +98 -52
- data/lib/tty/prompt/reader/codes.rb +63 -0
- data/lib/tty/prompt/reader/key_event.rb +67 -0
- data/lib/tty/prompt/reader/mode.rb +66 -0
- data/lib/tty/prompt/reader/mode/echo.rb +43 -0
- data/lib/tty/prompt/reader/mode/raw.rb +43 -0
- data/lib/tty/prompt/result.rb +42 -0
- data/lib/tty/prompt/statement.rb +9 -14
- data/lib/tty/prompt/suggestion.rb +4 -2
- data/lib/tty/prompt/symbols.rb +13 -0
- data/lib/tty/prompt/test.rb +3 -2
- data/lib/tty/prompt/utils.rb +1 -1
- data/lib/tty/prompt/version.rb +1 -1
- data/spec/unit/ask_spec.rb +31 -48
- data/spec/unit/choice/eql_spec.rb +0 -2
- data/spec/unit/choice/from_spec.rb +0 -2
- data/spec/unit/choices/add_spec.rb +0 -2
- data/spec/unit/choices/each_spec.rb +0 -2
- data/spec/unit/choices/new_spec.rb +0 -2
- data/spec/unit/choices/pluck_spec.rb +0 -2
- data/spec/unit/converters/convert_bool_spec.rb +58 -0
- data/spec/unit/{response/read_char_spec.rb → converters/convert_char_spec.rb} +2 -4
- data/spec/unit/converters/convert_custom_spec.rb +14 -0
- data/spec/unit/converters/convert_date_spec.rb +25 -0
- data/spec/unit/converters/convert_file_spec.rb +14 -0
- data/spec/unit/{response/read_number_spec.rb → converters/convert_number_spec.rb} +5 -7
- data/spec/unit/converters/convert_path_spec.rb +15 -0
- data/spec/unit/{response/read_range_spec.rb → converters/convert_range_spec.rb} +3 -5
- data/spec/unit/converters/convert_regex_spec.rb +12 -0
- data/spec/unit/converters/convert_string_spec.rb +21 -0
- data/spec/unit/distance/distance_spec.rb +0 -2
- data/spec/unit/error_spec.rb +0 -6
- data/spec/unit/evaluator_spec.rb +67 -0
- data/spec/unit/keypress_spec.rb +19 -0
- data/spec/unit/mask_spec.rb +95 -0
- data/spec/unit/multi_select_spec.rb +36 -24
- data/spec/unit/multiline_spec.rb +19 -0
- data/spec/unit/new_spec.rb +18 -0
- data/spec/unit/ok_spec.rb +10 -0
- data/spec/unit/question/default_spec.rb +17 -4
- data/spec/unit/question/echo_spec.rb +31 -0
- data/spec/unit/question/in_spec.rb +48 -16
- data/spec/unit/question/initialize_spec.rb +2 -9
- data/spec/unit/question/modifier/apply_to_spec.rb +9 -16
- data/spec/unit/question/modifier/letter_case_spec.rb +0 -2
- data/spec/unit/question/modifier/whitespace_spec.rb +12 -20
- data/spec/unit/question/modify_spec.rb +3 -7
- data/spec/unit/question/required_spec.rb +20 -14
- data/spec/unit/question/validate_spec.rb +20 -19
- data/spec/unit/question/validation/call_spec.rb +15 -6
- data/spec/unit/question/validation/coerce_spec.rb +17 -11
- data/spec/unit/reader/publish_keypress_event_spec.rb +81 -0
- data/spec/unit/reader/read_keypress_spec.rb +22 -0
- data/spec/unit/reader/read_line_spec.rb +31 -0
- data/spec/unit/reader/read_multiline_spec.rb +37 -0
- data/spec/unit/result_spec.rb +40 -0
- data/spec/unit/say_spec.rb +18 -23
- data/spec/unit/select_spec.rb +37 -32
- data/spec/unit/statement/initialize_spec.rb +4 -4
- data/spec/unit/suggest_spec.rb +0 -2
- data/spec/unit/warn_spec.rb +0 -5
- data/spec/unit/yes_no_spec.rb +70 -0
- data/tty-prompt.gemspec +7 -4
- metadata +123 -40
- data/lib/tty/prompt/codes.rb +0 -32
- data/lib/tty/prompt/cursor.rb +0 -131
- data/lib/tty/prompt/error.rb +0 -26
- data/lib/tty/prompt/mode.rb +0 -64
- data/lib/tty/prompt/mode/echo.rb +0 -41
- data/lib/tty/prompt/mode/raw.rb +0 -41
- data/lib/tty/prompt/response.rb +0 -247
- data/lib/tty/prompt/response_delegation.rb +0 -42
- data/spec/unit/cursor/new_spec.rb +0 -74
- data/spec/unit/question/character_spec.rb +0 -13
- data/spec/unit/reader/getc_spec.rb +0 -42
- data/spec/unit/response/read_bool_spec.rb +0 -58
- data/spec/unit/response/read_date_spec.rb +0 -16
- data/spec/unit/response/read_email_spec.rb +0 -45
- data/spec/unit/response/read_multiple_spec.rb +0 -21
- data/spec/unit/response/read_spec.rb +0 -69
- data/spec/unit/response/read_string_spec.rb +0 -14
@@ -0,0 +1,85 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Prompt
|
5
|
+
class Question
|
6
|
+
module Checks
|
7
|
+
# Check if modifications are applicable
|
8
|
+
class CheckModifier
|
9
|
+
def self.call(question, value)
|
10
|
+
if !question.modifier.nil? || question.modifier
|
11
|
+
[Modifier.new(question.modifier).apply_to(value)]
|
12
|
+
else
|
13
|
+
[value]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Check if value is within range
|
19
|
+
class CheckRange
|
20
|
+
def self.float?(value)
|
21
|
+
!/[-+]?(\d*[.])?\d+/.match(value.to_s).nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.int?(value)
|
25
|
+
!/^[-+]?\d+$/.match(value.to_s).nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.cast(value)
|
29
|
+
if float?(value)
|
30
|
+
value.to_f
|
31
|
+
elsif int?(value)
|
32
|
+
value.to_i
|
33
|
+
else
|
34
|
+
value
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.call(question, value)
|
39
|
+
if !question.in? ||
|
40
|
+
(question.in? && question.in.include?(cast(value)))
|
41
|
+
[value]
|
42
|
+
else
|
43
|
+
[value, ["Value #{value} is not included in the range #{question.in}"]]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Check if input requires validation
|
49
|
+
class CheckValidation
|
50
|
+
def self.call(question, value)
|
51
|
+
if !question.validation? ||
|
52
|
+
(question.validation? &&
|
53
|
+
Validation.new(question.validation).call(value))
|
54
|
+
[value]
|
55
|
+
else
|
56
|
+
[value, ["Your answer is invalid (must match #{question.validation.inspect})"]]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Check if default value provided
|
62
|
+
class CheckDefault
|
63
|
+
def self.call(question, value)
|
64
|
+
if value.nil? && question.default?
|
65
|
+
[question.default]
|
66
|
+
else
|
67
|
+
[value]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Check if input is required
|
73
|
+
class CheckRequired
|
74
|
+
def self.call(question, value)
|
75
|
+
if question.required? && !question.default? && value.nil?
|
76
|
+
[value, ['No value provided for required']]
|
77
|
+
else
|
78
|
+
[value]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end # Checks
|
83
|
+
end # Question
|
84
|
+
end # Prompt
|
85
|
+
end # TTY
|
@@ -6,13 +6,12 @@ module TTY
|
|
6
6
|
# A class representing String modifications.
|
7
7
|
class Modifier
|
8
8
|
attr_reader :modifiers
|
9
|
-
private :modifiers
|
10
9
|
|
11
10
|
# Initialize a Modifier
|
12
11
|
#
|
13
12
|
# @api public
|
14
|
-
def initialize(
|
15
|
-
@modifiers =
|
13
|
+
def initialize(modifiers)
|
14
|
+
@modifiers = modifiers
|
16
15
|
end
|
17
16
|
|
18
17
|
# Change supplied value according to the given string transformation.
|
@@ -26,8 +25,8 @@ module TTY
|
|
26
25
|
# @api private
|
27
26
|
def apply_to(value)
|
28
27
|
modifiers.reduce(value) do |result, mod|
|
29
|
-
result = Modifier.letter_case
|
30
|
-
Modifier.whitespace
|
28
|
+
result = Modifier.letter_case(mod, result)
|
29
|
+
Modifier.whitespace(mod, result)
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
@@ -5,53 +5,47 @@ module TTY
|
|
5
5
|
class Question
|
6
6
|
# A class representing question validation.
|
7
7
|
class Validation
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
attr_reader :pattern
|
9
|
+
|
10
|
+
VALIDATORS = {
|
11
|
+
email: /^[a-z0-9._%+-]+@([a-z0-9-]+\.)+[a-z]{2,6}$/i
|
12
|
+
}
|
11
13
|
|
12
14
|
# Initialize a Validation
|
13
15
|
#
|
14
|
-
# @param [Object]
|
16
|
+
# @param [Object] pattern
|
15
17
|
#
|
16
18
|
# @return [undefined]
|
17
19
|
#
|
18
20
|
# @api private
|
19
|
-
def initialize(
|
20
|
-
@
|
21
|
+
def initialize(pattern)
|
22
|
+
@pattern = coerce(pattern)
|
21
23
|
end
|
22
24
|
|
23
25
|
# Convert validation into known type.
|
24
26
|
#
|
25
|
-
# @param [Object]
|
27
|
+
# @param [Object] pattern
|
26
28
|
#
|
27
|
-
# @raise [TTY::ValidationCoercion]
|
29
|
+
# @raise [TTY::ValidationCoercion]
|
30
|
+
# raised when failed to convert validation
|
28
31
|
#
|
29
32
|
# @api private
|
30
|
-
def coerce(
|
31
|
-
case
|
32
|
-
when Proc
|
33
|
-
|
34
|
-
when Regexp
|
35
|
-
Regexp.new(
|
33
|
+
def coerce(pattern)
|
34
|
+
case pattern
|
35
|
+
when String, Symbol, Proc
|
36
|
+
pattern
|
37
|
+
when Regexp
|
38
|
+
Regexp.new(pattern.to_s)
|
36
39
|
else
|
37
|
-
fail ValidationCoercion, "Wrong type, got #{
|
40
|
+
fail ValidationCoercion, "Wrong type, got #{pattern.class}"
|
38
41
|
end
|
39
42
|
end
|
40
43
|
|
41
|
-
# Check if validation is required
|
42
|
-
#
|
43
|
-
# @return [Boolean]
|
44
|
-
#
|
45
|
-
# @api public
|
46
|
-
def validate?
|
47
|
-
!!validation
|
48
|
-
end
|
49
|
-
|
50
44
|
# Test if the input passes the validation
|
51
45
|
#
|
52
46
|
# @example
|
53
|
-
# Validation.new
|
54
|
-
# validation.
|
47
|
+
# Validation.new(/pattern/)
|
48
|
+
# validation.call(input) # => true
|
55
49
|
#
|
56
50
|
# @param [Object] input
|
57
51
|
# the input to validate
|
@@ -60,15 +54,15 @@ module TTY
|
|
60
54
|
#
|
61
55
|
# @api public
|
62
56
|
def call(input)
|
63
|
-
if
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
57
|
+
if pattern.is_a?(String) || pattern.is_a?(Symbol)
|
58
|
+
VALIDATORS.key?(pattern.to_sym)
|
59
|
+
!VALIDATORS[pattern.to_sym].match(input).nil?
|
60
|
+
elsif pattern.is_a?(Regexp)
|
61
|
+
!pattern.match(input).nil?
|
62
|
+
elsif pattern.is_a?(Proc)
|
63
|
+
result = pattern.call(input)
|
64
|
+
result.nil? ? false : result
|
65
|
+
else false
|
72
66
|
end
|
73
67
|
end
|
74
68
|
end # Validation
|
data/lib/tty/prompt/reader.rb
CHANGED
@@ -1,28 +1,37 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
require 'wisper'
|
4
|
+
require 'tty/prompt/reader/key_event'
|
5
|
+
require 'tty/prompt/reader/mode'
|
6
|
+
|
3
7
|
module TTY
|
4
8
|
# A class responsible for shell prompt interactions.
|
5
9
|
class Prompt
|
6
10
|
# A class responsible for reading character input from STDIN
|
7
11
|
class Reader
|
8
|
-
|
9
|
-
attr_reader :prompt
|
10
|
-
private :prompt
|
12
|
+
include Wisper::Publisher
|
11
13
|
|
12
14
|
attr_reader :mode
|
13
15
|
|
16
|
+
attr_reader :input
|
17
|
+
|
18
|
+
attr_reader :output
|
19
|
+
|
14
20
|
# Key input constants for decimal codes
|
15
21
|
CARRIAGE_RETURN = 13.freeze
|
16
22
|
NEWLINE = 10.freeze
|
17
23
|
BACKSPACE = 127.freeze
|
18
24
|
DELETE = 8.freeze
|
19
25
|
|
26
|
+
CSI = "\e[".freeze
|
27
|
+
|
20
28
|
# Initialize a Reader
|
21
29
|
#
|
22
30
|
# @api public
|
23
|
-
def initialize(
|
24
|
-
@
|
25
|
-
@
|
31
|
+
def initialize(input, output)
|
32
|
+
@input = input
|
33
|
+
@output = output
|
34
|
+
@mode = Mode.new
|
26
35
|
end
|
27
36
|
|
28
37
|
# Get input in unbuffered mode.
|
@@ -36,13 +45,11 @@ module TTY
|
|
36
45
|
#
|
37
46
|
# @api public
|
38
47
|
def buffer(&block)
|
39
|
-
bufferring =
|
48
|
+
bufferring = output.sync
|
40
49
|
# Immediately flush output
|
41
|
-
|
42
|
-
|
50
|
+
output.sync = true
|
43
51
|
value = block.call if block_given?
|
44
|
-
|
45
|
-
prompt.output.sync = bufferring
|
52
|
+
output.sync = bufferring
|
46
53
|
value
|
47
54
|
end
|
48
55
|
|
@@ -52,11 +59,14 @@ module TTY
|
|
52
59
|
# @return [String]
|
53
60
|
#
|
54
61
|
# @api public
|
55
|
-
def read_keypress
|
62
|
+
def read_keypress(echo = false)
|
56
63
|
buffer do
|
57
|
-
mode.echo(
|
64
|
+
mode.echo(echo) do
|
58
65
|
mode.raw(true) do
|
59
|
-
read_char
|
66
|
+
key = read_char
|
67
|
+
publish_keypress_event(key) if key
|
68
|
+
exit 130 if key == Codes::CTRL_C
|
69
|
+
key
|
60
70
|
end
|
61
71
|
end
|
62
72
|
end
|
@@ -68,78 +78,114 @@ module TTY
|
|
68
78
|
#
|
69
79
|
# @api public
|
70
80
|
def read_char
|
71
|
-
chars =
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
81
|
+
chars = input.sysread(1)
|
82
|
+
while CSI.start_with?(chars) ||
|
83
|
+
chars.start_with?(CSI) &&
|
84
|
+
!(64..126).include?(chars.each_codepoint.to_a.last)
|
85
|
+
next_char = read_char
|
86
|
+
chars << next_char
|
76
87
|
end
|
77
88
|
chars
|
78
|
-
rescue
|
89
|
+
rescue EOFError
|
90
|
+
# Finished processing
|
79
91
|
chars
|
80
92
|
end
|
81
93
|
|
82
|
-
# Get a
|
83
|
-
#
|
84
|
-
# enter key is pressed.
|
94
|
+
# Get a single line from STDIN
|
95
|
+
# Each key pressed is echoed back to the shell.
|
96
|
+
# The input terminates when enter or return key is pressed.
|
85
97
|
#
|
86
|
-
# @param [
|
87
|
-
#
|
98
|
+
# @param [Boolean] echo
|
99
|
+
# if true echo back characters, output nothing otherwise
|
88
100
|
#
|
89
101
|
# @return [String]
|
90
102
|
#
|
91
103
|
# @api public
|
92
|
-
def
|
93
|
-
|
104
|
+
def read_line(echo = true)
|
105
|
+
line = ''
|
94
106
|
buffer do
|
95
|
-
|
96
|
-
while (char =
|
107
|
+
mode.echo(echo) do
|
108
|
+
while (char = input.getbyte) &&
|
97
109
|
!(char == CARRIAGE_RETURN || char == NEWLINE)
|
98
|
-
|
110
|
+
publish_keypress_event(convert_byte(char))
|
111
|
+
line = handle_char(line, char)
|
99
112
|
end
|
100
|
-
ensure
|
101
|
-
mode.echo_on
|
102
113
|
end
|
103
114
|
end
|
104
|
-
|
115
|
+
line
|
116
|
+
end
|
117
|
+
|
118
|
+
# Read multiple lines and terminate when empty line is submitted.
|
119
|
+
#
|
120
|
+
# @yield [String] line
|
121
|
+
#
|
122
|
+
# @return [Array[String]]
|
123
|
+
#
|
124
|
+
# @api public
|
125
|
+
def read_multiline
|
126
|
+
response = []
|
127
|
+
loop do
|
128
|
+
line = read_line
|
129
|
+
break if !line || line == ''
|
130
|
+
next if line !~ /\S/
|
131
|
+
if block_given?
|
132
|
+
yield(line)
|
133
|
+
else
|
134
|
+
response << line
|
135
|
+
end
|
136
|
+
end
|
137
|
+
response
|
105
138
|
end
|
106
139
|
|
107
|
-
#
|
140
|
+
# Publish event
|
141
|
+
#
|
142
|
+
# @param [String] key
|
143
|
+
# the key pressed
|
144
|
+
#
|
145
|
+
# @return [nil]
|
108
146
|
#
|
109
147
|
# @api public
|
110
|
-
def
|
111
|
-
|
148
|
+
def publish_keypress_event(char)
|
149
|
+
event = KeyEvent.from(char)
|
150
|
+
event_name = parse_key_event(event)
|
151
|
+
publish(event_name, event) unless event_name.nil?
|
152
|
+
publish(:keypress, event)
|
112
153
|
end
|
113
154
|
|
114
|
-
#
|
155
|
+
# Interpret the key and provide event name
|
115
156
|
#
|
116
|
-
# @
|
157
|
+
# @return [Symbol]
|
117
158
|
#
|
118
159
|
# @api public
|
119
|
-
def
|
120
|
-
|
160
|
+
def parse_key_event(event)
|
161
|
+
return if event.key.nil?
|
162
|
+
permitted_events = %w(up down left right space return enter num)
|
163
|
+
return unless permitted_events.include?("#{event.key.name}")
|
164
|
+
:"key#{event.key.name}"
|
121
165
|
end
|
122
166
|
|
123
167
|
private
|
124
168
|
|
125
|
-
|
169
|
+
trap('SIGINT') { exit 130 }
|
170
|
+
|
171
|
+
# Convert byte to unicode character
|
172
|
+
#
|
173
|
+
# @return [String]
|
126
174
|
#
|
127
175
|
# @api private
|
128
|
-
def
|
129
|
-
|
130
|
-
value.slice!(-1, 1) unless value.empty?
|
131
|
-
else
|
132
|
-
print_char char, not_set, mask
|
133
|
-
value << char
|
134
|
-
end
|
135
|
-
value
|
176
|
+
def convert_byte(byte)
|
177
|
+
Array(byte).pack('U*')
|
136
178
|
end
|
137
179
|
|
138
|
-
#
|
180
|
+
# Handle single character by appending to or removing from output
|
139
181
|
#
|
140
182
|
# @api private
|
141
|
-
def
|
142
|
-
|
183
|
+
def handle_char(line, char)
|
184
|
+
if char == BACKSPACE || char == DELETE
|
185
|
+
line.empty? ? line : line.slice(-1, 1)
|
186
|
+
else
|
187
|
+
line << char
|
188
|
+
end
|
143
189
|
end
|
144
190
|
end # Reader
|
145
191
|
end # Prompt
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module TTY
|
4
|
+
class Prompt
|
5
|
+
class Reader
|
6
|
+
module Codes
|
7
|
+
BACKSPACE = "\177"
|
8
|
+
DELETE = "\004"
|
9
|
+
ESCAPE = "\e"
|
10
|
+
LINEFEED = "\n"
|
11
|
+
RETURN = "\r"
|
12
|
+
SPACE = " "
|
13
|
+
TAB = "\t"
|
14
|
+
|
15
|
+
KEY_UP = "\e[A"
|
16
|
+
KEY_DOWN = "\e[B"
|
17
|
+
KEY_RIGHT = "\e[C"
|
18
|
+
KEY_LEFT = "\e[D"
|
19
|
+
KEY_CLEAR = "\e[E"
|
20
|
+
KEY_END = "\e[F"
|
21
|
+
KEY_HOME = "\e[H"
|
22
|
+
KEY_DELETE = "\e[3"
|
23
|
+
|
24
|
+
KEY_UP_ALT = "\eOA"
|
25
|
+
KEY_DOWN_ALT = "\eOB"
|
26
|
+
KEY_RIGHT_ALT = "\eOC"
|
27
|
+
KEY_LEFT_ALT = "\eOD"
|
28
|
+
KEY_CLEAR_ALT = "\eOE"
|
29
|
+
KEY_END_ALT = "\eOF"
|
30
|
+
KEY_HOME_ALT = "\eOH"
|
31
|
+
KEY_DELETE_ALT = "\eO3"
|
32
|
+
|
33
|
+
CTRL_J = "\x0A"
|
34
|
+
CTRL_N = "\x0E"
|
35
|
+
CTRL_K = "\x0B"
|
36
|
+
CTRL_P = "\x10"
|
37
|
+
SIGINT = "\x03"
|
38
|
+
CTRL_C = "\x03"
|
39
|
+
CTRL_H = "\b"
|
40
|
+
CTRL_L = "\f"
|
41
|
+
|
42
|
+
F1 = "\eOP"
|
43
|
+
F2 = "\eOQ"
|
44
|
+
F3 = "\eOR"
|
45
|
+
F4 = "\eOS"
|
46
|
+
|
47
|
+
F1_ALT = "\e[11~"
|
48
|
+
F2_ALT = "\e[12~"
|
49
|
+
F3_ALT = "\e[13~"
|
50
|
+
F4_ALT = "\e[14~"
|
51
|
+
|
52
|
+
F5 = "\e[15~"
|
53
|
+
F6 = "\e[17~"
|
54
|
+
F7 = "\e[18~"
|
55
|
+
F8 = "\e[19~"
|
56
|
+
F9 = "\e[20~"
|
57
|
+
F10 = "\e[21~"
|
58
|
+
F11 = "\e[23~"
|
59
|
+
F12 = "\e[24~"
|
60
|
+
end # Codes
|
61
|
+
end # Reader
|
62
|
+
end # Prompt
|
63
|
+
end # TTY
|