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,229 @@
1
+ # = Fake server that replays transcripts to a client
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 'optparse'
20
+ require 'scriptty/net/event_loop'
21
+ require 'scriptty/util/transcript/reader'
22
+ require 'scriptty/term'
23
+ require 'logger'
24
+ require 'stringio'
25
+
26
+ module ScripTTY
27
+ module Apps
28
+ class ReplayApp
29
+ attr_reader :term
30
+
31
+ def initialize(argv)
32
+ @client_connection = nil
33
+ @server_connection = nil
34
+ @output_file = nil
35
+ @options = parse_options(argv)
36
+ @console_password = "" # TODO SECURITY FIXME
37
+ @attached_consoles = []
38
+ @log_stringio = StringIO.new
39
+ @log = Logger.new(@log_stringio)
40
+ @net = ScripTTY::Net::EventLoop.new
41
+ @input_transcript = []
42
+ @last_command = nil
43
+ end
44
+
45
+ def detach_console(console)
46
+ @attached_consoles.delete(console)
47
+ end
48
+
49
+ def log_messages
50
+ ([""]*10 + @log_stringio.string.split("\n"))[-10..-1].map{|line| line.sub(/^.*?\]/, '')}
51
+ end
52
+
53
+ def main
54
+ @output_file = Util::Transcript::Writer.new(File.open(@options[:output], "w")) if @options[:output]
55
+ @net.on_accept(@options[:console_addrs] || [], :multiple => true) do |conn|
56
+ p = CaptureApp::PasswordPrompt.new(conn, "Console password: ")
57
+ p.authenticate { |password| password == @console_password }
58
+ p.on_fail { conn.write("Authentiation failed.\r\n") { conn.close } }
59
+ p.on_success {
60
+ @attached_consoles << CaptureApp::Console.new(conn, self)
61
+ @attached_consoles.each { |c| c.refresh! }
62
+ }
63
+ end
64
+ @net.on_accept(@options[:listen_addrs], :multiple => true) do |conn|
65
+ @output_file.client_open(*conn.remote_address) if @output_file
66
+ @client_connection = conn
67
+ @client_connection.on_receive_bytes { |bytes| handle_client_receive_bytes(bytes) }
68
+ @client_connection.on_close { handle_client_close ; @client_connection = nil }
69
+ handle_client_connected
70
+ end
71
+ @net.main
72
+ ensure
73
+ if @output_file
74
+ @output_file.close
75
+ @output_file = nil
76
+ end
77
+ end
78
+
79
+ def handle_console_command_entered(cmd)
80
+ case cmd
81
+ when /^$/ # repeat last command
82
+ if @last_command
83
+ handle_console_command_entered(@last_command)
84
+ else
85
+ log.warn("No previous command entered")
86
+ end
87
+ return nil
88
+ when /^(\d*)(n|next)$/i # replay next step
89
+ count = $1 ? $1.to_i : 1
90
+ count.times { replay_next }
91
+ else
92
+ log.warn("Unknown console command: #{cmd}")
93
+ end
94
+ @last_command = cmd
95
+ end
96
+
97
+ # Instruct the event loop to exit.
98
+ #
99
+ # Can be invoked by another thread.
100
+ def exit
101
+ @net.exit
102
+ end
103
+
104
+ private
105
+
106
+ attr_reader :log
107
+
108
+ def handle_client_connected
109
+ @term = ScripTTY::Term.new(@options[:term])
110
+ @term.on_unknown_sequence do |sequence|
111
+ log.debug("Unknown escape sequence: #{sequence.inspect}")
112
+ end
113
+ replay_start
114
+ replay_next
115
+ refresh_consoles
116
+ end
117
+
118
+ def handle_client_receive_bytes(bytes)
119
+ log.info("Received from client: #{bytes.inspect}")
120
+ refresh_consoles
121
+ end
122
+
123
+ def handle_client_close
124
+ log.info("Client connection closed")
125
+ refresh_consoles
126
+ end
127
+
128
+ def replay_start
129
+ @next_bytes_to_send = nil
130
+ @transcript = []
131
+ @options[:input_files].each do |filename|
132
+ @transcript << ["--- File: #{filename} ---", nil]
133
+ reader = Util::Transcript::Reader.new
134
+ File.open(filename, "r") do |infile|
135
+ line_num = 0
136
+ until infile.eof?
137
+ line_num += 1
138
+ line = infile.readline
139
+ timestamp, type, args = reader.parse_line(line)
140
+ if type == :from_server
141
+ @transcript << ["(#{line_num}) #{line.strip}", args[0]]
142
+ elsif type == :server_parsed
143
+ @transcript << ["(#{line_num}) #{line.strip}", args[1]]
144
+ else
145
+ @transcript << ["(#{line_num}) #{line.strip}", nil]
146
+ end
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ def replay_next
153
+ if @next_bytes_to_send
154
+ @client_connection.write(@next_bytes_to_send) { refresh_consoles }
155
+ @term.feed_bytes(@next_bytes_to_send)
156
+ @next_bytes_to_send = nil
157
+ end
158
+ until @transcript.empty?
159
+ display, bytes = @transcript.shift
160
+ if bytes
161
+ log.debug("NXTD: #{display}") # next data
162
+ @next_bytes_to_send = bytes
163
+ break
164
+ else
165
+ log.debug("INFO: #{display}")
166
+ end
167
+ end
168
+ if @transcript.empty?
169
+ log.debug("DONE")
170
+ end
171
+ end
172
+
173
+ def refresh_consoles
174
+ @attached_consoles.each { |c| c.refresh! }
175
+ end
176
+
177
+ def parse_options(argv)
178
+ args = argv.dup
179
+ options = {:listen_addrs => [], :console_addrs => []}
180
+ opts = OptionParser.new do |opts|
181
+ opts.banner = "Usage: #{opts.program_name} [options] FILE"
182
+ opts.separator "Stream capture application"
183
+ opts.on("-l", "--listen [HOST]:PORT", "Listen on the specified HOST:PORT") do |optarg|
184
+ addr = parse_hostport(optarg, :allow_empty_host => true, :allow_zero_port => true)
185
+ options[:listen_addrs] << addr
186
+ end
187
+ opts.on("-C", "--console [HOST]:PORT", "Debug console on the specified HOST:PORT") do |optarg|
188
+ addr = parse_hostport(optarg, :allow_empty_host => true, :allow_zero_port => true)
189
+ options[:console_addrs] << addr
190
+ end
191
+ opts.on("-t", "--term NAME", "Terminal to emulate") do |optarg|
192
+ raise ArgumentError.new("Unsupported terminal #{optarg.inspect}") unless ScripTTY::Term::TERMINAL_TYPES.include?(optarg)
193
+ options[:term] = optarg
194
+ end
195
+ end
196
+ opts.parse!(args)
197
+ if args.length < 1
198
+ $stderr.puts "error: No input file(s) specified."
199
+ exit 1
200
+ end
201
+ unless !options[:listen_addrs].empty? and !options[:console_addrs].empty? and options[:term]
202
+ $stderr.puts "error: --listen, --console, and --term are mandatory"
203
+ exit 1
204
+ end
205
+ options[:input_files] = args
206
+ options
207
+ end
208
+
209
+ # Parse [HOST:]PORT into separate host and port. Host is optional, and
210
+ # might be surrounded by square brackets.
211
+ def parse_hostport(s, opts={})
212
+ unless s =~ /\A(\[[^\[\]]*\]|[^\[\]]*):(\d+)\Z/
213
+ raise ArgumentError.new("Unable to parse host:port")
214
+ end
215
+ host, port = [$1, $2]
216
+ host.gsub!(/\A\[(.*?)\]\Z/, '\1')
217
+ port = port.to_i
218
+ raise ArgumentError.new("Invalid port") if port < 0 or port > 0xffff or (port == 0 and !opts[:allow_zero_port])
219
+ unless opts[:allow_empty_host]
220
+ raise ArgumentError.new("Host cannot be empty") if host.empty?
221
+ end
222
+ [host, port]
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ require 'scriptty/apps/capture_app/password_prompt'
229
+ require 'scriptty/apps/capture_app/console'
@@ -0,0 +1,124 @@
1
+ # = Terminal emulation testing app
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 'optparse'
20
+ require 'scriptty/term'
21
+ require 'scriptty/util/transcript/reader'
22
+
23
+ module ScripTTY
24
+ module Apps
25
+ class TermTestApp
26
+ def initialize(argv)
27
+ @options = parse_options(argv)
28
+ end
29
+
30
+ def log(message)
31
+ @log_buffer << message
32
+ @log_file.puts(message) if @log_file
33
+ end
34
+
35
+ def main
36
+ @log_buffer = []
37
+ @log_file = @options[:log] && File.open(@options[:log], "w")
38
+ @term = ScripTTY::Term.new(@options[:term])
39
+ @term.on_unknown_sequence do |seq|
40
+ log "Unknown escape sequence: #{seq.inspect}"
41
+ end
42
+ $stdout.print "\ec" # Reset terminal; clear the screen
43
+ $stdout.flush
44
+ time_multiplier = @options[:rate] > 0 ? 1.0/@options[:rate] : 0
45
+ @options[:input_files].each do |inp|
46
+ File.open(inp[:path], "rb") do |input_file|
47
+ time0 = Time.now
48
+ timestamp0 = timestamp = nil
49
+ reader = Util::Transcript::Reader.new
50
+ until input_file.eof?
51
+ # Read a chunk of the input file
52
+ case inp[:format]
53
+ when :binary
54
+ c = input_file.read(1)
55
+ @term.feed_byte(c)
56
+ when :capture
57
+ timestamp, type, args = reader.parse_line(input_file.readline)
58
+ next unless type == :from_server
59
+ bytes = args[0]
60
+
61
+ # Wait until the time specified in the timestamp passes
62
+ timestamp0 = timestamp unless timestamp0 # treat the first timestamp as time 0
63
+ sleep_time = (timestamp-timestamp0)*time_multiplier - (Time.now - time0)
64
+ sleep(sleep_time) if sleep_time > 0
65
+
66
+ @term.feed_bytes(bytes)
67
+ else
68
+ raise "BUG: Invalid format: #{inp[:format]}"
69
+ end
70
+
71
+ # Output the screen contents
72
+ screen_lines = []
73
+ screen_lines << "Timestamp: #{timestamp}" if timestamp
74
+ screen_lines << "Cursor position: #{@term.cursor_pos.inspect}"
75
+ screen_lines += @term.debug_info if @term.respond_to?(:debug_info)
76
+ screen_lines << "+" + "-"*@term.width + "+"
77
+ @term.text.each do |line|
78
+ screen_lines << "|#{line}|"
79
+ end
80
+ screen_lines << "+" + "-"*@term.width + "+"
81
+ screen_lines << "--- Log ---"
82
+ ([0,@log_buffer.length-10].max..@log_buffer.length-1).each do |i|
83
+ screen_lines << sprintf("%3d: %s", i+1, @log_buffer[i])
84
+ end
85
+ screen_lines << "--- End of log ---"
86
+ screen_lines << ""
87
+ $stdout.puts "\e[H" + screen_lines.map{|line| "\e[2K" + line}.join("\n")
88
+ $stdout.flush
89
+ end
90
+ end
91
+ end
92
+ @log_file.close if @log_file
93
+ end
94
+
95
+ private
96
+ def parse_options(argv)
97
+ args = argv.dup
98
+ options = {:term => 'xterm', :input_files => [], :rate => 2}
99
+ opts = OptionParser.new do |opts|
100
+ opts.banner = "Usage: #{opts.program_name} [options]"
101
+ opts.separator "Debug a specified terminal emulator"
102
+ opts.on("-t", "--term NAME", "Terminal to emulate") do |optarg|
103
+ raise ArgumentError.new("Unsupported terminal #{optarg.inspect}") unless ScripTTY::Term::TERMINAL_TYPES.include?(optarg)
104
+ options[:term] = optarg
105
+ end
106
+ opts.on("-b", "--binary-input FILE", "Binary file to read") do |optarg|
107
+ options[:input_files] << {:path => optarg, :format => :binary}
108
+ end
109
+ opts.on("-c", "--capture-input FILE", "Capture-format file to read") do |optarg|
110
+ options[:input_files] << {:path => optarg, :format => :capture}
111
+ end
112
+ opts.on("-r", "--rate RATE", "Playback at the specified rate (0 for infinite; default: #{options[:rate]})") do |optarg|
113
+ options[:rate] = optarg.to_f
114
+ end
115
+ opts.on("-L", "--log FILE", "Write log to FILE") do |optarg|
116
+ options[:log] = optarg
117
+ end
118
+ end
119
+ opts.parse!(args)
120
+ options
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,143 @@
1
+ # = Transcript parsing app
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 'optparse'
20
+ require 'scriptty/term'
21
+ require 'scriptty/util/transcript/reader'
22
+ require 'scriptty/util/transcript/writer'
23
+
24
+ module ScripTTY
25
+ module Apps
26
+ class TranscriptParseApp
27
+ def initialize(argv)
28
+ @options = parse_options(argv)
29
+ end
30
+
31
+ def main
32
+ File.open(@options[:output], "w") do |output_file|
33
+ @writer = ScripTTY::Util::Transcript::Writer.new(output_file)
34
+ @options[:input_files].each do |input_filename|
35
+ File.open(input_filename, "rb") do |input_file|
36
+ reader = ScripTTY::Util::Transcript::Reader.new
37
+ @last_printable = nil
38
+ parser_class = ScripTTY::Term.class_by_name(@options[:term]).parser_class
39
+
40
+ # Set up server-side FSM
41
+ @server_parser = parser_class.new :callback => Proc.new { |event_name, fsm|
42
+ if event_name == :t_printable
43
+ # Merge printable character sequences together, rather than writing individual "t_printable" events.
44
+ @last_server_printable ||= ""
45
+ @last_server_printable += fsm.input_sequence.join
46
+ else
47
+ flush_server_printable
48
+ @writer.server_parsed(event_name, fsm.input_sequence.join)
49
+ end
50
+ }
51
+ @server_parser.on_unknown_sequence { |seq| @writer.server_parsed("?", seq) }
52
+
53
+ # Set up client-side FSM
54
+ if @options[:client]
55
+ @client_parser = parser_class.new :client => true, :callback => Proc.new { |event_name, fsm|
56
+ if event_name == :t_printable
57
+ # Merge printable character sequences together, rather than writing individual "t_printable" events.
58
+ @last_client_printable ||= ""
59
+ @last_client_printable += fsm.input_sequence.join
60
+ else
61
+ flush_client_printable
62
+ @writer.client_parsed(event_name, fsm.input_sequence.join)
63
+ end
64
+ }
65
+ @client_parser.on_unknown_sequence { |seq| @writer.client_parsed("?", seq) }
66
+ end
67
+
68
+ until input_file.eof?
69
+ timestamp, type, args = reader.parse_line(input_file.readline)
70
+ @writer.override_timestamp = timestamp
71
+ if type == :from_server
72
+ @writer.send(type, *args) if @options[:keep]
73
+ bytes = args[0]
74
+ @server_parser.feed_bytes(bytes)
75
+ elsif type == :from_client and @client_parser
76
+ @writer.send(type, *args) if @options[:keep]
77
+ bytes = args[0]
78
+ @client_parser.feed_bytes(bytes)
79
+ else
80
+ @writer.send(type, *args)
81
+ end
82
+ end
83
+ flush_server_printable
84
+ flush_client_printable if @client_parser
85
+ end
86
+ end
87
+ @writer.close
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ def flush_server_printable
94
+ if @last_server_printable
95
+ @writer.server_parsed(".", @last_server_printable)
96
+ @last_server_printable = nil
97
+ end
98
+ end
99
+
100
+ def flush_client_printable
101
+ if @last_client_printable
102
+ @writer.client_parsed(".", @last_client_printable)
103
+ @last_client_printable = nil
104
+ end
105
+ end
106
+
107
+ def parse_options(argv)
108
+ args = argv.dup
109
+ options = {:input_files => []}
110
+ opts = OptionParser.new do |opts|
111
+ opts.banner = "Usage: #{opts.program_name} [options] FILE..."
112
+ opts.separator "Parse transcript escape sequences according to a specified terminal emulation,"
113
+ opts.separator 'converting raw "S" transcript entries into parsed "Sp" entries.'
114
+
115
+ opts.on("-t", "--term NAME", "Terminal to emulate") do |optarg|
116
+ raise ArgumentError.new("Unsupported terminal #{optarg.inspect}") unless ScripTTY::Term::TERMINAL_TYPES.include?(optarg)
117
+ options[:term] = optarg
118
+ end
119
+ opts.on("-k", "--keep", 'Keep original "S" lines in the transcript') do |optarg|
120
+ options[:keep] = optarg
121
+ end
122
+ opts.on("-c", "--[no-]client", "Also parse client (\"C\") entries") do |optarg|
123
+ options[:client] = optarg
124
+ end
125
+ opts.on("-o", "--output FILE", "Write output to FILE") do |optarg|
126
+ options[:output] = optarg
127
+ end
128
+ end
129
+ opts.parse!(args)
130
+ if args.length < 1
131
+ $stderr.puts "error: No input file(s) specified."
132
+ exit 1
133
+ end
134
+ unless options[:output] and options[:term]
135
+ $stderr.puts "error: --output and --term are mandatory"
136
+ exit 1
137
+ end
138
+ options[:input_files] = args
139
+ options
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,39 @@
1
+ # = Cursor object
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
+ module ScripTTY
20
+ class Cursor
21
+ attr_accessor :row, :column
22
+ def initialize
23
+ @row = 0
24
+ @column = 0
25
+ end
26
+
27
+ def pos
28
+ [@row, @column]
29
+ end
30
+
31
+ def pos=(value)
32
+ raise TypeError.new("must be 2-element array") unless value.is_a?(Array) and value.length == 2
33
+ @row, @column = value
34
+ @row ||= 0
35
+ @column ||= 0
36
+ value
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ # = ScripTTY exceptions
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
+ module ScripTTY
20
+ module Exception
21
+ # Exception base class
22
+ class Base < StandardError
23
+ end
24
+
25
+ # Raised when a script times out.
26
+ class Timeout < Base
27
+ end
28
+
29
+ # Raised when a connection error occurs
30
+ class ConnectError < Base
31
+ attr_accessor :orig_exception
32
+ def initialize(exception)
33
+ @orig_exception = exception
34
+ super("Connect error (#{exception.class.name}): #{exception}")
35
+ end
36
+ end
37
+ end
38
+ end