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.
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