scriptty 0.5.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitattributes +1 -0
  2. data/.gitignore +3 -0
  3. data/COPYING +674 -0
  4. data/COPYING.LESSER +165 -0
  5. data/README.rdoc +31 -0
  6. data/Rakefile +49 -0
  7. data/VERSION +1 -0
  8. data/bin/scriptty-capture +5 -0
  9. data/bin/scriptty-dump-screens +4 -0
  10. data/bin/scriptty-replay +5 -0
  11. data/bin/scriptty-term-test +4 -0
  12. data/bin/scriptty-transcript-parse +4 -0
  13. data/examples/captures/xterm-overlong-line-prompt.bin +9 -0
  14. data/examples/captures/xterm-vim-session.bin +262 -0
  15. data/examples/demo-capture.rb +19 -0
  16. data/examples/telnet-nego.rb +55 -0
  17. data/lib/scriptty/apps/capture_app/console.rb +104 -0
  18. data/lib/scriptty/apps/capture_app/password_prompt.rb +65 -0
  19. data/lib/scriptty/apps/capture_app.rb +213 -0
  20. data/lib/scriptty/apps/dump_screens_app.rb +166 -0
  21. data/lib/scriptty/apps/replay_app.rb +229 -0
  22. data/lib/scriptty/apps/term_test_app.rb +124 -0
  23. data/lib/scriptty/apps/transcript_parse_app.rb +143 -0
  24. data/lib/scriptty/cursor.rb +39 -0
  25. data/lib/scriptty/exception.rb +38 -0
  26. data/lib/scriptty/expect.rb +392 -0
  27. data/lib/scriptty/multiline_buffer.rb +192 -0
  28. data/lib/scriptty/net/event_loop.rb +610 -0
  29. data/lib/scriptty/screen_pattern/generator.rb +398 -0
  30. data/lib/scriptty/screen_pattern/parser.rb +558 -0
  31. data/lib/scriptty/screen_pattern.rb +104 -0
  32. data/lib/scriptty/term/dg410/dg410-client-escapes.txt +37 -0
  33. data/lib/scriptty/term/dg410/dg410-escapes.txt +82 -0
  34. data/lib/scriptty/term/dg410/parser.rb +162 -0
  35. data/lib/scriptty/term/dg410.rb +489 -0
  36. data/lib/scriptty/term/xterm/xterm-escapes.txt +73 -0
  37. data/lib/scriptty/term/xterm.rb +661 -0
  38. data/lib/scriptty/term.rb +40 -0
  39. data/lib/scriptty/util/fsm/definition_parser.rb +111 -0
  40. data/lib/scriptty/util/fsm/scriptty_fsm_definition.treetop +189 -0
  41. data/lib/scriptty/util/fsm.rb +177 -0
  42. data/lib/scriptty/util/transcript/reader.rb +96 -0
  43. data/lib/scriptty/util/transcript/writer.rb +111 -0
  44. data/test/apps/capture_app_test.rb +123 -0
  45. data/test/apps/transcript_parse_app_test.rb +118 -0
  46. data/test/cursor_test.rb +51 -0
  47. data/test/fsm_definition_parser_test.rb +220 -0
  48. data/test/fsm_test.rb +322 -0
  49. data/test/multiline_buffer_test.rb +275 -0
  50. data/test/net/event_loop_test.rb +402 -0
  51. data/test/screen_pattern/generator_test.rb +408 -0
  52. data/test/screen_pattern/parser_test/explicit_cursor_pattern.txt +14 -0
  53. data/test/screen_pattern/parser_test/explicit_fields.txt +22 -0
  54. data/test/screen_pattern/parser_test/multiple_patterns.txt +42 -0
  55. data/test/screen_pattern/parser_test/simple_pattern.txt +14 -0
  56. data/test/screen_pattern/parser_test/truncated_heredoc.txt +12 -0
  57. data/test/screen_pattern/parser_test/utf16bebom_pattern.bin +0 -0
  58. data/test/screen_pattern/parser_test/utf16lebom_pattern.bin +0 -0
  59. data/test/screen_pattern/parser_test/utf8_pattern.bin +14 -0
  60. data/test/screen_pattern/parser_test/utf8_unix_pattern.bin +14 -0
  61. data/test/screen_pattern/parser_test/utf8bom_pattern.bin +14 -0
  62. data/test/screen_pattern/parser_test.rb +266 -0
  63. data/test/term/dg410/parser_test.rb +139 -0
  64. data/test/term/xterm_test.rb +327 -0
  65. data/test/test_helper.rb +3 -0
  66. data/test/util/transcript/reader_test.rb +131 -0
  67. data/test/util/transcript/writer_test.rb +126 -0
  68. data/test.watchr +29 -0
  69. 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