tty-prompt 0.2.0 → 0.3.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 +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
|