fcshd 0.3.1 → 0.5

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/Makefile CHANGED
@@ -1,6 +1,12 @@
1
+ version=$(shell ruby -r lib/fcshd/version -e 'print FCSHD::VERSION')
2
+
3
+ default: install
4
+
1
5
  build:
2
6
  gem build fcshd.gemspec
7
+ install: build
8
+ sudo gem install fcshd-${version}.gem
9
+ push: build
10
+ gem push fcshd-${version}.gem
3
11
  clean:
4
12
  rm *.gem
5
- push: build
6
- gem push fcshd-$(shell ruby -r lib/fcshd/version -e 'print FCSHD::VERSION').gem
data/bin/fcshc CHANGED
@@ -16,82 +16,159 @@ def die(message)
16
16
  exit 1
17
17
  end
18
18
 
19
- $source_directories = []
20
- $library_filenames = []
19
+ $output_file = nil
20
+ $source_files = []
21
+ $library_files = []
22
+ $directories = []
23
+ $production = false
21
24
  $extra_arguments = []
25
+ $verbose = false
26
+ $dry_run = false
22
27
 
23
28
  OptionParser.new do |parser|
24
- parser.banner = "Usage: fcshc MAIN [SRCDIR|LIB]... -o OUTPUT"
29
+ parser.banner = <<EOF
30
+ Usage: fcshc MAIN.[as|mxml] [SRCDIR|SWCDIR|SWC]... [-o OUTPUT.swf]
31
+ fcshc -o OUTPUT.swc [SRCDIR|SWCDIR|SWC]...
25
32
 
26
- parser.on("-o", "--output FILENAME", "Write SWF to FILENAME") do |value|
27
- $output_filename = File.expand_path(value)
33
+ To compile an SWF, name the main application source file, then any
34
+ additional source directories, SWC directories, or SWC files.
35
+
36
+ To compile an SWC using `compc', you must provide the `-o' option, and
37
+ then at least one source directory, SWC directory, or SWC file.
38
+
39
+ To pass extra arguments, use e.g. `-X -include-file -X NAME -X FILE'.
40
+
41
+ EOF
42
+
43
+ parser.on("-o", "--output OUTPUT.[swf|swc]", "Name of the resulting binary") do |value|
44
+ $output_file = File.expand_path(value)
28
45
  end
29
46
 
30
- parser.on("-3", "Use -compatibility-version=3") do |value|
31
- $extra_arguments << "-compatibility-version=3"
47
+ parser.on("-X", "--extra-argument ARGUMENT", "Pass ARGUMENT to the compiler") do |value|
48
+ $extra_arguments << value
32
49
  end
33
50
 
34
- parser.on("--no-flex", "Remove all runtime shared libraries (RSLs)") do
51
+ parser.on("-p", "--production", "Leave out debugging metadata") do
52
+ $production = true
53
+ end
54
+
55
+ parser.on("--static-rsls", "Use static linking for RSLs") do
56
+ $extra_arguments << "-static-link-runtime-shared-libraries=true"
57
+ end
58
+
59
+ parser.on("--no-rsls", "Remove all runtime shared libraries") do
35
60
  $extra_arguments << "-runtime-shared-library-path="
36
61
  end
37
62
 
63
+ parser.separator ""
64
+
65
+ parser.on("-3", "--flex-3", "Use -compatibility-version=3") do |value|
66
+ $extra_arguments << "-compatibility-version=3"
67
+ end
68
+
38
69
  parser.on("--halo", "Use the Halo theme") do
39
70
  die "must set $FLEX_HOME to use --halo option" if not FlexHome.known?
40
71
  $extra_arguments << "-theme=#{FlexHome.halo_swc}"
41
72
  end
42
73
 
43
- parser.on("-X EXTRA-ARGUMENT", "Pass EXTRA-ARGUMENT to mxmlc (multiple allowed)") do |value|
44
- $extra_arguments << value
74
+ parser.separator ""
75
+
76
+ parser.on("-n", "--dry-run", "Only print the compiler command") do
77
+ $dry_run = true
45
78
  end
46
79
 
47
- parser.on("-v", "--verbose", "Print mxmlc command line") do
80
+ parser.on("--verbose", "Also print the compiler command") do
48
81
  $verbose = true
49
82
  end
83
+
84
+ parser.on("-v", "--version", "Show `fcshc #{FCSHD::VERSION}'") do
85
+ puts "fcshc #{FCSHD::VERSION}"
86
+ exit
87
+ end
88
+
89
+ parser.on("-h", "--help", "Show this message") do
90
+ puts parser
91
+ exit
92
+ end
93
+
94
+ parser.separator ""
95
+ parser.separator "TL;DR: $ fcshc src/my_app.mxml"
50
96
  end.parse!
51
97
 
98
+ $extra_arguments << "-debug" unless $production
99
+
52
100
  for name in ARGV
53
101
  if not File.exists? name
54
102
  die "no such file or directory: #{name}"
55
103
  elsif File.directory? name
56
- $source_directories << File.expand_path(name)
104
+ $directories << File.expand_path(name)
57
105
  elsif %w(.as .mxml).include? File.extname(name)
58
- die "multiple source files not allowed" if $source_filename
59
- $source_filename = File.expand_path(name)
106
+ $source_files << File.expand_path(name)
60
107
  elsif %w(.swc).include? File.extname(name)
61
- $library_filenames << File.expand_path(name)
108
+ $library_files << File.expand_path(name)
62
109
  else
63
110
  die "don't know what to do with file: #{name}"
64
111
  end
65
112
  end
66
113
 
67
- if $source_filename == nil
68
- die "missing source file to compile"
69
- end
114
+ $compiling_swc = $output_file && $output_file.end_with?(".swc")
70
115
 
71
- if $source_directories == []
72
- $source_directories << File.dirname($source_filename)
73
- end
116
+ if $compiling_swc
117
+ if [$source_files, $directories, $library_files] == [[], [], []]
118
+ die "must include at least one source file, directory, or SWC"
119
+ end
120
+
121
+ $fcshd_arguments = ["compc"]
122
+
123
+ for file in $source_files
124
+ $fcshd_arguments << "-include-sources+=#{file}"
125
+ end
126
+
127
+ for directory in $directories
128
+ $fcshd_arguments << "-include-sources+=#{directory}"
129
+ end
130
+ else
131
+ case $source_files.size
132
+ when 0: die "missing main application source file"
133
+ when 1: $source_file = $source_files.first
134
+ else die "multiple source files not allowed when compiling SWF"
135
+ end
136
+
137
+ if $directories.empty?
138
+ $directories << File.dirname($source_file)
139
+ end
74
140
 
75
- if $output_filename == nil
76
- $source_filename.sub(/\.(as|mxml)$/, ".swf").tap do |filename|
77
- local_filename = File.basename(filename)
78
- $output_filename = File.expand_path(local_filename)
141
+ if $output_file == nil
142
+ $source_file.sub(/\.(as|mxml)$/, ".swf").tap do |x|
143
+ $output_file = File.expand_path(File.basename(x))
144
+ end
79
145
  end
146
+
147
+ $fcshd_arguments = ["mxmlc", "#$source_file"]
80
148
  end
81
149
 
82
- $fcshd_arguments = ["mxmlc #$source_filename -output=#$output_filename"]
150
+ $fcshd_arguments << "-output=#$output_file"
83
151
 
84
- for directory in $source_directories
152
+ for directory in $directories
85
153
  $fcshd_arguments << "-compiler.source-path+=#{directory}"
86
154
  $fcshd_arguments << "-compiler.library-path+=#{directory}"
87
155
  end
88
156
 
89
- for filename in $library_filenames
90
- $fcshd_arguments << "-compiler.library-path+=#{filename}"
157
+ for file in $library_files
158
+ $fcshd_arguments << "-compiler.library-path+=#{file}"
91
159
  end
92
160
 
93
161
  $fcshd_arguments.concat($extra_arguments)
94
162
 
163
+ basedir = File.join(File.expand_path("."), "")
164
+ fcshd_command = $fcshd_arguments.join(" ")
165
+
166
+ if $verbose || $dry_run
167
+ warn fcshd_command.gsub(basedir, "")
168
+ end
169
+
170
+ exit if $dry_run
171
+
95
172
  begin
96
173
  host, port = "localhost", FCSHD::Server::PORT
97
174
  socket = TCPSocket.new(host, port)
@@ -99,10 +176,6 @@ rescue Errno::ECONNREFUSED
99
176
  die "could not connect to fcshd at #{host}:#{port}"
100
177
  end
101
178
 
102
- basedir = File.join(File.expand_path("."), "")
103
-
104
- fcshd_command = $fcshd_arguments.join(" ")
105
- warn fcshd_command.gsub(basedir, "") if $verbose
106
179
  socket.puts fcshd_command
107
180
 
108
181
  compiler_output = ""
@@ -115,7 +188,6 @@ socket.each_line do |line|
115
188
  end
116
189
  end
117
190
 
118
- output = FCSHD::CompilerOutput[compiler_output, basedir]
119
- output.write! FCSHD::CompilerOutputWriter.new(STDOUT, basedir)
120
-
121
- exit 1 if not output.succeeded?
191
+ transcript = FCSHD::Transcript[compiler_output]
192
+ STDOUT.write transcript.to_s(basedir)
193
+ exit 1 if not transcript.succeeded?
data/bin/fcshd CHANGED
@@ -8,6 +8,11 @@ rescue LoadError
8
8
  require "fcshd"
9
9
  end
10
10
 
11
+ if ARGV == ["-v"] || ARGV == ["--version"]
12
+ puts "fcshd #{FCSHD::VERSION}"
13
+ exit
14
+ end
15
+
11
16
  logger = FCSHD::Logger.new(STDERR)
12
17
 
13
18
  logger.die <<"^D" if not FCSHD::FlexHome.known?
@@ -26,6 +31,7 @@ begin
26
31
  FCSHD::Server.new(FCSHD::Server::PORT, compiler, logger).run!
27
32
  logger.log "Now listening to port #{FCSHD_PORT}."
28
33
  rescue Interrupt
34
+ logger.log ""
29
35
  logger.log "Exiting."
30
36
  rescue Exception => error
31
37
  logger.error "Could not listen to port #{FCSHD_PORT}: #{error}"
@@ -51,7 +51,7 @@ module FCSHD
51
51
  end
52
52
 
53
53
  def compile_new!
54
- @frontend.puts "fcshd: compiling from scratch"
54
+ @frontend.puts "fcshd: Compiling from scratch"
55
55
  @frontend.flush
56
56
  send_fcsh_command! @command
57
57
  parse_compilation_output!
data/lib/fcshd/problem.rb CHANGED
@@ -1,153 +1,7 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  module FCSHD
4
- class Problem < Struct.new(:source_location, :raw_mxmlc_message)
5
- ERROR_PREFIX = /^\s*Error: /
6
-
7
- def mxmlc_message
8
- raw_mxmlc_message.sub(ERROR_PREFIX, "")
9
- end
10
-
11
- def error?
12
- raw_mxmlc_message =~ ERROR_PREFIX
13
- end
14
-
15
- def quote(string)
16
- "‘#{string}’"
17
- end
18
-
19
- def message
20
- case raw = raw_message
21
- when String then raw
22
- when Array then raw * "\n"
23
- else fail
24
- end
25
- end
26
-
27
- def raw_message
28
- case mxmlc_message
29
-
30
- when "Unable to resolve MXML language version. Please specify the language namespace on the root document tag."
31
- then
32
- <<"^D"
33
- missing MXML version
34
- → xmlns:fx="library://ns.adobe.com/mxml/2009"
35
- → xmlns="library://ns.adobe.com/flex/spark"
36
- → xmlns:mx="library://ns.adobe.com/flex/mx" (Flex 3 compatibility)
37
- → xmlns="http://www.adobe.com/2006/mxml" (Flex 3)
38
- ^D
39
-
40
- when /^Incorrect number of arguments. Expected (\d+)\.$/
41
- then "expected #$1 arguments"
42
-
43
- when /^(?:Access of possibly undefined property|Call to a possibly undefined method) (.+) through a reference with static type (.+)\.$/
44
- then "#{quote $1} undeclared in #$2"
45
-
46
- when /^Attempted access of inaccessible property (.+) through a reference with static type (.+)\.$/
47
- then "#{quote $1} inaccessible in #$2"
48
-
49
- when
50
- /^Could not resolve <(.+)> to a component implementation.$/,
51
- /^Call to a possibly undefined method (.+).$/,
52
- /^Access of undefined property (.+).$/,
53
- /^The definition of base class (.+) was not found.$/,
54
- /^Type was not found or was not a compile-time constant: (.+)\.$/
55
- then
56
- ["#{quote $1} undeclared"].tap do |result|
57
- FlexHome.find_component($1).tap do |package|
58
- result << "→ import #{package}.*" if package
59
- end
60
- end
61
-
62
- when /^Definition (.+) could not be found\.$/
63
- then "#{quote $1} not found"
64
-
65
- when
66
- /^Implicit coercion of a value of type (.+) to an unrelated type (.+)\.$/,
67
-
68
- /^Implicit coercion of a value with static type (.+) to a possibly unrelated type (.+)\./
69
-
70
- then
71
- actual, expected = $1, $2
72
- expected_base = expected.sub(/.+:/, "")
73
- actual_base = actual.sub(/.+:/, "")
74
- if actual_base != expected_base
75
- "expected #{expected_base} (got #{actual_base})"
76
- else
77
- "expected #{expected} (got #{actual})"
78
- end
79
-
80
- when "Method marked override must override another method."
81
- then "overriding nonexistent method"
82
-
83
- when "Overriding a function that is not marked for override."
84
- then ["unmarked override", "→ add override keyword"]
85
-
86
- when "Incompatible override."
87
- then "incompatible override"
88
-
89
- when /^Ambiguous reference to (.+)\.$/
90
- then "#{quote $1} is ambiguous"
91
-
92
- when /^A conflict exists with definition (.+) in namespace internal\.$/
93
- then "#{quote $1} is conflicting"
94
-
95
- when
96
- /^Warning: parameter '(.+)' has no type declaration\.$/,
97
- /^Warning: return value for function '(.+)' has no type declaration\.$/
98
- then
99
- case $1
100
- when "anonymous" then "anonymous function"
101
- else quote $1
102
- end + " missing type declaration"
103
-
104
- when /^A file found in a source-path must have the same package structure '(.*)', as the definition's package, '(.*)'\.$/
105
- then "package should be #{quote $1}"
106
-
107
- when /^Comparison between a value with static type (.+) and a possibly unrelated type (.+)\.$/
108
- then "comparing #$1 to #$2"
109
-
110
- when "Illegal assignment to a variable specified as constant."
111
- then "modifying constant"
112
-
113
- when "Function does not have a body."
114
- then "missing function body"
115
-
116
- when "Return type of a setter definition must be unspecified or void."
117
- then "setter must return void"
118
-
119
- when "Function does not return a value."
120
- then "missing return statement"
121
-
122
- when "Syntax error: expecting identifier before rightparen."
123
- then "#{quote ")"} unexpected"
124
-
125
- when
126
- /^The (.+) attribute can only be used inside a package\./,
127
- /^The (.+) attribute may be used only on class property definitions\./
128
- then
129
- "#{quote $1} unexpected"
130
-
131
- else
132
- mxmlc_message
133
- end
134
- end
135
-
136
- def formatted_message_lines
137
- lines = message.lines.entries
138
- if error?
139
- first = <<"^D"
140
- error: #{lines[0].chomp}
141
- ^D
142
- rest = lines[1..-1].map do |line|
143
- <<"^D"
144
- #{line.chomp}
145
- ^D
146
- end
147
- [first] + rest
148
- else
149
- lines
150
- end
2
+ class Problem < Struct.new(:location, :message)
3
+ def to_s(basedir)
4
+ "#{location.to_s(basedir)}: #{message}"
151
5
  end
152
6
  end
153
7
  end
data/lib/fcshd/server.rb CHANGED
@@ -21,10 +21,10 @@ module FCSHD
21
21
  class Client < Struct.new(:socket, :compiler)
22
22
  def run!
23
23
  case command = socket.gets
24
- when /^mxmlc /
24
+ when /^(mxmlc|compc) /
25
25
  compiler.compile! command, socket
26
26
  else
27
- sockets.puts "fcshd: unrecognized command: #{command}"
27
+ socket.puts "fcshd: unrecognized command: #{command}"
28
28
  end
29
29
  rescue Errno::EPIPE
30
30
  logger.log "Broken pipe."
@@ -1,27 +1,15 @@
1
1
  module FCSHD
2
- class SourceLocation < Struct.new \
3
- :filename, :line_number, :column_number, :basedir
4
-
5
- def to_s
6
- relative_filename.tap do |result|
7
- result << ":#{line_number}" if line_number
8
- end
2
+ class SourceLocation < Struct.new(:filename, :line_number)
3
+ def to_s(basedir=nil)
4
+ "#{relative_filename(basedir)}:#{line_number || 0}"
9
5
  end
10
6
 
11
- def relative_filename
7
+ def relative_filename(basedir)
12
8
  if basedir
13
9
  filename.sub(/^#{Regexp.quote(basedir)}/, "")
14
10
  else
15
11
  filename
16
12
  end
17
13
  end
18
-
19
- def with_basedir(new_basedir)
20
- dup.tap { |result| result.basedir = new_basedir }
21
- end
22
-
23
- def without_column_number
24
- dup.tap { |result| result.column_number = nil }
25
- end
26
14
  end
27
15
  end
@@ -0,0 +1,154 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module FCSHD
4
+ class Transcript; end
5
+ class Transcript::Item < Struct.new(:location, :mxmlc_message)
6
+ def to_s(basedir)
7
+ problems.map { |problem| problem.to_s(basedir) }.join("\n")
8
+ end
9
+
10
+ def problems
11
+ get_problems(parsed_message)
12
+ end
13
+
14
+ private
15
+
16
+ def get_problems(item)
17
+ case item
18
+ when String
19
+ get_problems_at(location, item)
20
+ when Array
21
+ if item.first.is_a? SourceLocation
22
+ get_problems_at(item[0], item[1])
23
+ else
24
+ item.map { |item| get_problems(item) }.flatten(1)
25
+ end
26
+ else fail
27
+ end
28
+ end
29
+
30
+ def get_problems_at(location, message)
31
+ message.split("\n").map do |message|
32
+ Problem[location, message]
33
+ end
34
+ end
35
+
36
+ def parsed_message
37
+ case FCSHD.trim(mxmlc_message).sub(/^Error: /, "")
38
+ when "Unable to resolve MXML language version. Please specify the language namespace on the root document tag.": <<EOF
39
+ error: missing MXML version
40
+ error: hint: xmlns:fx="library://ns.adobe.com/mxml/2009"
41
+ error: hint: xmlns="library://ns.adobe.com/flex/spark"
42
+ error: hint: xmlns:mx="library://ns.adobe.com/flex/mx" (Flex 4)
43
+ error: hint: xmlns="http://www.adobe.com/2006/mxml" (Flex 3)
44
+ EOF
45
+ when /^Incorrect number of arguments. Expected (\d+)\.$/: <<EOF
46
+ error: expected #$1 arguments
47
+ EOF
48
+ when
49
+ /^Access of possibly undefined property (.+) through a reference with static type (.+)\.$/,
50
+ /^Call to a possibly undefined method (.+) through a reference with static type (.+)\.$/,
51
+ /^Cannot resolve attribute '(.+)' for component type (.+)\.$/
52
+ then <<EOF
53
+ error: #{quote $1} undeclared in #{name $2}
54
+ EOF
55
+ when /^Attempted access of inaccessible property (.+) through a reference with static type (.+)\.$/: <<EOF
56
+ error: #{quote $1} inaccessible in #{name $2}
57
+ EOF
58
+ when
59
+ /^Could not resolve <(.+)> to a component implementation\.$/,
60
+ /^Call to a possibly undefined method (.+)\.$/,
61
+ /^Access of undefined property (.+)\.$/,
62
+ /^The definition of base class (.+) was not found\.$/,
63
+ /^Type was not found or was not a compile-time constant: (.+)\.$/
64
+ then
65
+ [<<EOF].tap do |result|
66
+ error: #{quote $1} undeclared
67
+ EOF
68
+ FlexHome.find_component($1).tap do |package|
69
+ result << <<EOF if package
70
+ error: hint: import #{package}.#$1
71
+ EOF
72
+ end
73
+ end
74
+ when /^Definition (.+) could not be found\.$/: <<EOF
75
+ error: #{quote $1} not found
76
+ EOF
77
+ when /^Implicit coercion of a value of type (.+) to an unrelated type (.+)\.$/, /^Implicit coercion of a value with static type (.+) to a possibly unrelated type (.+)\./
78
+ actual, expected = $1, $2
79
+ expected_local = expected.sub(/.+:/, "")
80
+ actual_local = actual.sub(/.+:/, "")
81
+ actual_local != expected_local ? <<EOF : <<EOF
82
+ error: expected #{expected_local} (got #{actual_local})
83
+ EOF
84
+ error: expected #{expected} (got #{actual})
85
+ EOF
86
+ when "Method marked override must override another method.": <<EOF
87
+ error: overriding nonexistent method
88
+ EOF
89
+ when "Overriding a function that is not marked for override.": <<EOF
90
+ error: unmarked override
91
+ EOF
92
+ when "Incompatible override.": <<EOF
93
+ error: incompatible override
94
+ EOF
95
+ when /^Ambiguous reference to (.+)\.$/: <<EOF
96
+ error: #{quote $1} is ambiguous
97
+ EOF
98
+ when /^Can not resolve a multiname reference unambiguously. (\S+) \(from ([^)]+)\) and (\S+) \(from ([^)]+)\) are available\.$/
99
+ then
100
+ [<<EOF, [SourceLocation[$2], <<EOF], [SourceLocation[$4], <<EOF]]
101
+ error: #{quote name $1} conflicts with #{quote name $3}
102
+ EOF
103
+ error: conflicting definition
104
+ EOF
105
+ error: conflicting definition
106
+ EOF
107
+ when /^A conflict exists with definition (.+) in namespace internal\.$/: <<EOF
108
+ error: #{quote $1} conflicts with an internal name
109
+ EOF
110
+ when
111
+ /^Warning: parameter '(.+)' has no type declaration\.$/,
112
+ /^Warning: return value for function '(.+)' has no type declaration\.$/
113
+ then
114
+ who = $1 == "anonymous" ? "anonymous function" : quote($1)
115
+ <<EOF
116
+ error: #{who} missing type declaration
117
+ EOF
118
+ when /^A file found in a source-path must have the same package structure '(.*)', as the definition's package, '(.*)'\.$/: <<EOF
119
+ error: package should be #{quote $1}
120
+ EOF
121
+ when /^Comparison between a value with static type (.+) and a possibly unrelated type (.+)\.$/: <<EOF
122
+ error: comparing #$1 to #$2
123
+ EOF
124
+ when "Illegal assignment to a variable specified as constant.": <<EOF
125
+ error: modifying constant
126
+ EOF
127
+ when "Function does not have a body.": <<EOF
128
+ error: missing function body"
129
+ EOF
130
+ when "Return type of a setter definition must be unspecified or void.": <<EOF
131
+ error: setter must return void"
132
+ EOF
133
+ when "Function does not return a value.": <<EOF
134
+ error: missing return statement"
135
+ EOF
136
+ when "Syntax error: expecting identifier before rightparen.": <<EOF
137
+ error: #{quote ")"} unexpected"
138
+ EOF
139
+ when
140
+ /^The (.+) attribute can only be used inside a package\./,
141
+ /^The (.+) attribute may be used only on class property definitions\./
142
+ then
143
+ <<EOF
144
+ error: #{quote $1} unexpected
145
+ EOF
146
+ else
147
+ mxmlc_message
148
+ end
149
+ end
150
+
151
+ def quote(string) "‘#{string}’" end
152
+ def name(string) string.sub! ":", "." end
153
+ end
154
+ end
@@ -0,0 +1,65 @@
1
+ module FCSHD
2
+ class Transcript; end
3
+ class Transcript::Parser < Struct.new(:lines)
4
+ def parse!
5
+ Transcript.new.tap do |result|
6
+ @result = result
7
+ parse_line! until lines.empty?
8
+ end
9
+ end
10
+
11
+ attr_reader :result
12
+
13
+ def parse_line!
14
+ take_line! do |line|
15
+ case FCSHD.trim(line)
16
+ when / \((\d+) bytes\)$/
17
+ result.succeeded = true
18
+
19
+ when "Nothing has changed since the last compile. Skip..."
20
+ result.n_compiled_files = 0
21
+
22
+ when /^Files changed: (\d+) Files affected: (\d+)$/
23
+ result.n_compiled_files = $1.to_i + $2.to_i
24
+
25
+ when /^(\/.+?)(?:\((\d+)\))?: (?:col: \d+ )?(.+)$/
26
+ result << Transcript::Item[SourceLocation[$1, $2.to_i], $3]
27
+ skip_indented_lines! # Ignore the "diagram" of the problem.
28
+
29
+ when /^Required RSLs:$/
30
+ skip_indented_lines! # Does anybody care about this?
31
+
32
+ when /^(Recompile|Reason): /
33
+ when /^Loading configuration file /
34
+
35
+ else
36
+ # Let unrecognized lines pass through verbatim.
37
+ if line.start_with? "fcshd: "
38
+ result << line
39
+ else
40
+ # XXX: What about when we support compc?
41
+ result << "mxmlc: #{line}"
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def take_line!
48
+ yield skip_line!
49
+ end
50
+
51
+ def skip_line!
52
+ current_line
53
+ ensure
54
+ lines.shift
55
+ end
56
+
57
+ def current_line
58
+ lines.first.chomp
59
+ end
60
+
61
+ def skip_indented_lines!
62
+ skip_line! until lines.empty? or current_line =~ /^\S/
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,35 @@
1
+ module FCSHD
2
+ class Transcript
3
+ def self.[] text
4
+ Parser.new(text.split("\n")).parse!
5
+ end
6
+
7
+ def initialize
8
+ @items = []
9
+ end
10
+
11
+ def << item
12
+ @items << item
13
+ end
14
+
15
+ attr_accessor :n_compiled_files
16
+
17
+ def succeeded= value; @succeeded = value; end
18
+ def succeeded?; @succeeded; end
19
+
20
+ def to_s(basedir)
21
+ @items.map do |item|
22
+ case item
23
+ when Item
24
+ item.to_s(basedir)
25
+ else
26
+ item.to_s
27
+ end
28
+ end.join("\n")
29
+ end
30
+
31
+ def nothing_to_do?
32
+ n_compiled_files == 0
33
+ end
34
+ end
35
+ end
data/lib/fcshd/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  unless defined? FCSHD::VERSION
2
2
  module FCSHD
3
- VERSION = "0.3.1"
3
+ VERSION = "0.5"
4
4
  end
5
5
  end
data/lib/fcshd.rb CHANGED
@@ -1,9 +1,16 @@
1
+ module FCSHD
2
+ def self.trim(string)
3
+ string.gsub(/\s+/, " ").gsub(/^ | $/, "")
4
+ end
5
+ end
6
+
1
7
  require "fcshd/compiler"
2
- require "fcshd/compiler-output"
3
- require "fcshd/compiler-output-writer"
4
8
  require "fcshd/flex-home"
5
9
  require "fcshd/logger"
6
10
  require "fcshd/problem"
7
11
  require "fcshd/server"
8
12
  require "fcshd/source-location"
13
+ require "fcshd/transcript"
14
+ require "fcshd/transcript-item"
15
+ require "fcshd/transcript-parser"
9
16
  require "fcshd/version"
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fcshd
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 1
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 3
9
- - 1
10
- version: 0.3.1
8
+ - 5
9
+ version: "0.5"
11
10
  platform: ruby
12
11
  authors:
13
12
  - Daniel Brockman
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2011-11-02 00:00:00 Z
17
+ date: 2011-12-01 00:00:00 Z
19
18
  dependencies: []
20
19
 
21
20
  description: |
@@ -42,14 +41,15 @@ files:
42
41
  - bin/fcshd
43
42
  - fcshd.gemspec
44
43
  - lib/fcshd.rb
45
- - lib/fcshd/compiler-output-writer.rb
46
- - lib/fcshd/compiler-output.rb
47
44
  - lib/fcshd/compiler.rb
48
45
  - lib/fcshd/flex-home.rb
49
46
  - lib/fcshd/logger.rb
50
47
  - lib/fcshd/problem.rb
51
48
  - lib/fcshd/server.rb
52
49
  - lib/fcshd/source-location.rb
50
+ - lib/fcshd/transcript-item.rb
51
+ - lib/fcshd/transcript-parser.rb
52
+ - lib/fcshd/transcript.rb
53
53
  - lib/fcshd/version.rb
54
54
  homepage: http://github.com/dbrock/fcshd
55
55
  licenses: []
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
80
  requirements: []
81
81
 
82
82
  rubyforge_project:
83
- rubygems_version: 1.8.10
83
+ rubygems_version: 1.8.11
84
84
  signing_key:
85
85
  specification_version: 3
86
86
  summary: Usable CLI for the Adobe Flex compiler shell (fcsh)
@@ -1,19 +0,0 @@
1
- module FCSHD
2
- class CompilerOutputWriter
3
- def initialize(output, basedir)
4
- @output = output
5
- @basedir = basedir
6
- end
7
-
8
- def write_uninterpreted_line! line
9
- @output.puts line
10
- end
11
-
12
- def write_problem! problem
13
- location = problem.source_location.with_basedir(@basedir)
14
- for line in problem.formatted_message_lines do
15
- @output.puts "#{location}: #{line}"
16
- end
17
- end
18
- end
19
- end
@@ -1,91 +0,0 @@
1
- module FCSHD
2
- class CompilerOutput
3
- def self.[] text, basedir
4
- new.tap do |result|
5
- Parser.new(text.lines.entries, basedir, result).parse!
6
- end
7
- end
8
-
9
- attr_accessor :n_compiled_files
10
-
11
- def initialize
12
- @events = []
13
- end
14
-
15
- def << event
16
- @events << event
17
- end
18
-
19
- def write! writer
20
- for event in @events
21
- case event
22
- when String
23
- writer.write_uninterpreted_line! event
24
- when Problem
25
- writer.write_problem! event
26
- end
27
- end
28
- end
29
-
30
- def nothing_to_do?
31
- n_compiled_files == 0
32
- end
33
-
34
- def succeeded!
35
- @succeeded = true
36
- end
37
-
38
- def succeeded?
39
- @succeeded
40
- end
41
-
42
- class Parser < Struct.new(:lines, :basedir, :result)
43
- def parse!
44
- parse_line! until lines.empty?
45
- end
46
-
47
- def parse_line!
48
- take_line! do |line|
49
- case line
50
- when /^(Recompile|Reason): /
51
- when /^Loading configuration file /
52
- when /^(.+\.swf) \((\d+) bytes\)$/
53
- result.succeeded!
54
- when "Nothing has changed since the last compile. Skip..."
55
- result.n_compiled_files = 0
56
- when /^Files changed: (\d+) Files affected: (\d+)$/
57
- result.n_compiled_files = $1.to_i + $2.to_i
58
- when /^(\/.+?)(?:\((\d+)\))?: (?:col: (\d+) )?(.+)$/
59
- location = SourceLocation[$1, $2.to_i, $3.to_i, basedir]
60
- result << Problem[location, $4]
61
- skip_indented_lines!
62
- when /^Required RSLs:$/
63
- skip_indented_lines!
64
- when /^fcshd: /
65
- result << line
66
- else
67
- result << "mxmlc: #{line}"
68
- end
69
- end
70
- end
71
-
72
- def take_line!
73
- yield skip_line!
74
- end
75
-
76
- def skip_line!
77
- current_line
78
- ensure
79
- lines.shift
80
- end
81
-
82
- def current_line
83
- lines[0].chomp
84
- end
85
-
86
- def skip_indented_lines!
87
- skip_line! until lines.empty? or current_line =~ /^\S/
88
- end
89
- end
90
- end
91
- end