scriptty 0.5.0-java
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.
- data/.gitattributes +1 -0
- data/.gitignore +3 -0
- data/COPYING +674 -0
- data/COPYING.LESSER +165 -0
- data/README.rdoc +31 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/bin/scriptty-capture +5 -0
- data/bin/scriptty-dump-screens +4 -0
- data/bin/scriptty-replay +5 -0
- data/bin/scriptty-term-test +4 -0
- data/bin/scriptty-transcript-parse +4 -0
- data/examples/captures/xterm-overlong-line-prompt.bin +9 -0
- data/examples/captures/xterm-vim-session.bin +262 -0
- data/examples/demo-capture.rb +19 -0
- data/examples/telnet-nego.rb +55 -0
- data/lib/scriptty/apps/capture_app/console.rb +104 -0
- data/lib/scriptty/apps/capture_app/password_prompt.rb +65 -0
- data/lib/scriptty/apps/capture_app.rb +213 -0
- data/lib/scriptty/apps/dump_screens_app.rb +166 -0
- data/lib/scriptty/apps/replay_app.rb +229 -0
- data/lib/scriptty/apps/term_test_app.rb +124 -0
- data/lib/scriptty/apps/transcript_parse_app.rb +143 -0
- data/lib/scriptty/cursor.rb +39 -0
- data/lib/scriptty/exception.rb +38 -0
- data/lib/scriptty/expect.rb +392 -0
- data/lib/scriptty/multiline_buffer.rb +192 -0
- data/lib/scriptty/net/event_loop.rb +610 -0
- data/lib/scriptty/screen_pattern/generator.rb +398 -0
- data/lib/scriptty/screen_pattern/parser.rb +558 -0
- data/lib/scriptty/screen_pattern.rb +104 -0
- data/lib/scriptty/term/dg410/dg410-client-escapes.txt +37 -0
- data/lib/scriptty/term/dg410/dg410-escapes.txt +82 -0
- data/lib/scriptty/term/dg410/parser.rb +162 -0
- data/lib/scriptty/term/dg410.rb +489 -0
- data/lib/scriptty/term/xterm/xterm-escapes.txt +73 -0
- data/lib/scriptty/term/xterm.rb +661 -0
- data/lib/scriptty/term.rb +40 -0
- data/lib/scriptty/util/fsm/definition_parser.rb +111 -0
- data/lib/scriptty/util/fsm/scriptty_fsm_definition.treetop +189 -0
- data/lib/scriptty/util/fsm.rb +177 -0
- data/lib/scriptty/util/transcript/reader.rb +96 -0
- data/lib/scriptty/util/transcript/writer.rb +111 -0
- data/test/apps/capture_app_test.rb +123 -0
- data/test/apps/transcript_parse_app_test.rb +118 -0
- data/test/cursor_test.rb +51 -0
- data/test/fsm_definition_parser_test.rb +220 -0
- data/test/fsm_test.rb +322 -0
- data/test/multiline_buffer_test.rb +275 -0
- data/test/net/event_loop_test.rb +402 -0
- data/test/screen_pattern/generator_test.rb +408 -0
- data/test/screen_pattern/parser_test/explicit_cursor_pattern.txt +14 -0
- data/test/screen_pattern/parser_test/explicit_fields.txt +22 -0
- data/test/screen_pattern/parser_test/multiple_patterns.txt +42 -0
- data/test/screen_pattern/parser_test/simple_pattern.txt +14 -0
- data/test/screen_pattern/parser_test/truncated_heredoc.txt +12 -0
- data/test/screen_pattern/parser_test/utf16bebom_pattern.bin +0 -0
- data/test/screen_pattern/parser_test/utf16lebom_pattern.bin +0 -0
- data/test/screen_pattern/parser_test/utf8_pattern.bin +14 -0
- data/test/screen_pattern/parser_test/utf8_unix_pattern.bin +14 -0
- data/test/screen_pattern/parser_test/utf8bom_pattern.bin +14 -0
- data/test/screen_pattern/parser_test.rb +266 -0
- data/test/term/dg410/parser_test.rb +139 -0
- data/test/term/xterm_test.rb +327 -0
- data/test/test_helper.rb +3 -0
- data/test/util/transcript/reader_test.rb +131 -0
- data/test/util/transcript/writer_test.rb +126 -0
- data/test.watchr +29 -0
- metadata +175 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
# Terminal escapes for dg410
|
2
|
+
#'\001' => t_print_form
|
3
|
+
#'\002' => t_stx
|
4
|
+
'\003' => t_blink_enable
|
5
|
+
'\004' => t_blink_disable
|
6
|
+
#'\005' => t_read_window_address
|
7
|
+
'\006' => t_proprietary_ack
|
8
|
+
'\007' => t_bell
|
9
|
+
'\010' => t_window_home
|
10
|
+
#'\011' => t_tab
|
11
|
+
'\012' => t_new_line
|
12
|
+
'\013' => t_erase_end_of_line
|
13
|
+
'\014' => t_erase_window
|
14
|
+
'\015' => t_carriage_return
|
15
|
+
'\016' => t_blink_on
|
16
|
+
'\017' => t_blink_off
|
17
|
+
'\020' => {
|
18
|
+
* => {
|
19
|
+
* => t_write_window_address
|
20
|
+
}
|
21
|
+
}
|
22
|
+
'\021' => t_print_window
|
23
|
+
'\022' => t_roll_enable
|
24
|
+
'\023' => t_roll_disable
|
25
|
+
'\024' => t_underscore_on
|
26
|
+
'\025' => t_underscore_off
|
27
|
+
#'\026' => t_syn # seems to always be followed by some data, then \002 # XXX TODO
|
28
|
+
'\027' => t_cursor_up
|
29
|
+
'\030' => t_cursor_right
|
30
|
+
'\031' => t_cursor_left
|
31
|
+
'\032' => t_cursor_down
|
32
|
+
'\033' => {
|
33
|
+
# '\x20' => {
|
34
|
+
# 'i' => t_esc_sp_i
|
35
|
+
# }
|
36
|
+
# '*' => {
|
37
|
+
# 's' => t_esc_asterisk_s
|
38
|
+
# }
|
39
|
+
']' => { # OSC? -- Nope XXX TODO
|
40
|
+
[01] => {
|
41
|
+
'M' => t_osc_m # XXX TODO
|
42
|
+
'K' => t_osc_k # XXX TODO
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
'\034' => t_dim_on
|
47
|
+
'\035' => t_dim_off
|
48
|
+
'\036' => {
|
49
|
+
# 'C' => t_read_model_id
|
50
|
+
'D' => t_reverse_video_on
|
51
|
+
'E' => t_reverse_video_off
|
52
|
+
'F' => {
|
53
|
+
'A' => t_reset
|
54
|
+
'F' => t_erase_unprotected
|
55
|
+
# 'I' => t_delete_line
|
56
|
+
'Q' => {
|
57
|
+
* => t_set_cursor_type
|
58
|
+
}
|
59
|
+
# '\\' => t_delete_between_margins
|
60
|
+
# '@' => t_select_ansi_mode
|
61
|
+
}
|
62
|
+
# 'K' => t_delete_character
|
63
|
+
'~' => t_parse_proprietary_escape
|
64
|
+
}
|
65
|
+
'\377' => {
|
66
|
+
'\372' => t_parse_telnet_sb => {
|
67
|
+
* => t_telnet_subnegotiation
|
68
|
+
}
|
69
|
+
'\373' => {
|
70
|
+
* => t_telnet_will
|
71
|
+
}
|
72
|
+
'\374' => {
|
73
|
+
* => t_telnet_wont
|
74
|
+
}
|
75
|
+
'\375' => {
|
76
|
+
* => t_telnet_do
|
77
|
+
}
|
78
|
+
'\376' => {
|
79
|
+
* => t_telnet_dont
|
80
|
+
}
|
81
|
+
}
|
82
|
+
[\x20-\x7e] => t_printable
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# = Parser for DG410 terminal
|
2
|
+
# Copyright (C) 2010 Infonium Inc.
|
3
|
+
#
|
4
|
+
# This file is part of ScripTTY.
|
5
|
+
#
|
6
|
+
# ScripTTY is free software: you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU Lesser General Public License as published
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
9
|
+
# (at your option) any later version.
|
10
|
+
#
|
11
|
+
# ScripTTY is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
# GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public License
|
17
|
+
# along with ScripTTY. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
|
19
|
+
require 'scriptty/term/dg410'
|
20
|
+
|
21
|
+
module ScripTTY # :nodoc:
|
22
|
+
module Term
|
23
|
+
class DG410 # reopen
|
24
|
+
class Parser
|
25
|
+
SERVER_PARSER_DEFINITION = File.read(File.join(File.dirname(__FILE__), "dg410-escapes.txt"))
|
26
|
+
CLIENT_PARSER_DEFINITION = File.read(File.join(File.dirname(__FILE__), "dg410-client-escapes.txt"))
|
27
|
+
|
28
|
+
# ScripTTY::Util::FSM object used by this parser. (Used for debugging.)
|
29
|
+
attr_reader :fsm
|
30
|
+
|
31
|
+
def initialize(options={})
|
32
|
+
@fsm = Util::FSM.new(
|
33
|
+
:definition => options[:client] ? CLIENT_PARSER_DEFINITION : SERVER_PARSER_DEFINITION,
|
34
|
+
:callback => self, :callback_method => :handle_event)
|
35
|
+
@callback = options[:callback]
|
36
|
+
@callback_method = options[:callback_method] || :call
|
37
|
+
on_unknown_sequence :error
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set the behaviour of the terminal when an unknown escape sequence is
|
41
|
+
# found.
|
42
|
+
#
|
43
|
+
# This method takes either a symbol or a block.
|
44
|
+
#
|
45
|
+
# When a block is given, it is executed whenever an unknown escape
|
46
|
+
# sequence is received. The block is passed the escape sequence as a
|
47
|
+
# single string.
|
48
|
+
#
|
49
|
+
# When a symbol is given, it may be one of the following:
|
50
|
+
# [:error]
|
51
|
+
# (default) Raise a ScripTTY::Util::FSM::NoMatch exception.
|
52
|
+
# [:ignore]
|
53
|
+
# Ignore the unknown escape sequence.
|
54
|
+
def on_unknown_sequence(mode=nil, &block)
|
55
|
+
if !block and !mode
|
56
|
+
raise ArgumentError.new("No mode specified and no block given")
|
57
|
+
elsif block and mode
|
58
|
+
raise ArgumentError.new("Block and mode are mutually exclusive, but both were given")
|
59
|
+
elsif block
|
60
|
+
@on_unknown_sequence = block
|
61
|
+
elsif [:error, :ignore].include?(mode)
|
62
|
+
@on_unknown_sequence = mode
|
63
|
+
else
|
64
|
+
raise ArgumentError.new("Invalid mode #{mode.inspect}")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Feed the specified byte to the terminal. Returns a string of
|
69
|
+
# bytes that should be transmitted (e.g. for TELNET negotiation).
|
70
|
+
def feed_byte(byte)
|
71
|
+
raise ArgumentError.new("input should be single byte") unless byte.is_a?(String) and byte.length == 1
|
72
|
+
begin
|
73
|
+
@fsm.process(byte)
|
74
|
+
rescue Util::FSM::NoMatch => e
|
75
|
+
@fsm.reset!
|
76
|
+
if @on_unknown_sequence == :error
|
77
|
+
raise
|
78
|
+
elsif @on_unknown_sequence == :ignore
|
79
|
+
# do nothing
|
80
|
+
elsif !@on_unknown_sequence.is_a?(Symbol) # @on_unknown_sequence is a Proc
|
81
|
+
@on_unknown_sequence.call(e.input_sequence.join)
|
82
|
+
else
|
83
|
+
raise "BUG"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
""
|
87
|
+
end
|
88
|
+
|
89
|
+
# Convenience method: Feeds several bytes to the terminal. Returns a
|
90
|
+
# string of bytes that should be transmitted (e.g. for TELNET
|
91
|
+
# negotiation).
|
92
|
+
def feed_bytes(bytes)
|
93
|
+
retvals = []
|
94
|
+
bytes.split(//n).each do |byte|
|
95
|
+
retvals << feed_byte(byte)
|
96
|
+
end
|
97
|
+
retvals.join
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def handle_event(event, fsm)
|
103
|
+
if respond_to?(event, true)
|
104
|
+
send(event, fsm)
|
105
|
+
else
|
106
|
+
@callback.__send__(@callback_method, event, fsm) if @callback
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Parse proprietary escape code, and fire the :t_proprietary_escape
|
111
|
+
# event when finished.
|
112
|
+
def t_parse_proprietary_escape(fsm)
|
113
|
+
state = 0
|
114
|
+
length = nil
|
115
|
+
header_length = 5
|
116
|
+
fsm.redirect = lambda {|fsm|
|
117
|
+
if fsm.input_sequence.length == header_length
|
118
|
+
length = fsm.input.unpack("C*")[0]
|
119
|
+
end
|
120
|
+
if length && fsm.input_sequence.length >= header_length + length
|
121
|
+
fsm.redirect = nil
|
122
|
+
fsm.fire_event(:t_proprietary_escape)
|
123
|
+
end
|
124
|
+
true
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
# IAC SB ... SE
|
129
|
+
def t_parse_telnet_sb(fsm)
|
130
|
+
# limit subnegotiation to 100 chars # FIXME - This is wrong
|
131
|
+
count = 0
|
132
|
+
fsm.redirect = lambda {|fsm| count += 1; count < 100 && fsm.input_sequence[-2..-1] != ["\377", "\360"]}
|
133
|
+
end
|
134
|
+
|
135
|
+
# Parse ANSI/DEC CSI escape sequence parameters. Pass in fsm.input_sequence
|
136
|
+
#
|
137
|
+
# Example:
|
138
|
+
# parse_csi_params("\e[H") # returns []
|
139
|
+
# parse_csi_params("\e[;H") # returns []
|
140
|
+
# parse_csi_params("\e[2J") # returns [2]
|
141
|
+
# parse_csi_params("\e[33;42;0m") # returns [33, 42, 0]
|
142
|
+
# parse_csi_params(["\e", "[", "3", "3", ";", "4" "2", ";" "0", "m"]) # same as above, but takes an array
|
143
|
+
#
|
144
|
+
# This also works with DEC escape sequences:
|
145
|
+
# parse_csi_params("\e[?1;2J") # returns [1,2]
|
146
|
+
def parse_csi_params(input_seq) # TODO - test this
|
147
|
+
seq = input_seq.join if input_seq.respond_to?(:join) # Convert array to string
|
148
|
+
unless seq =~ /\A\e\[\??([\d;]*)[^\d]\Z/n
|
149
|
+
raise "BUG"
|
150
|
+
end
|
151
|
+
$1.split(/;/n).map{|p|
|
152
|
+
if p.empty?
|
153
|
+
nil
|
154
|
+
else
|
155
|
+
p.to_i
|
156
|
+
end
|
157
|
+
}
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|