fcshd 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ *.gem
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2@fcshd --create
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,14 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ fcshd (0)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+
10
+ PLATFORMS
11
+ ruby
12
+
13
+ DEPENDENCIES
14
+ fcshd!
@@ -0,0 +1,116 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require "fcshd"
5
+ rescue LoadError
6
+ require "pathname"
7
+ $: << File.expand_path("../../lib", Pathname.new(__FILE__).realpath)
8
+ require "fcshd"
9
+ end
10
+
11
+ require "optparse"
12
+ require "socket"
13
+
14
+ def die(message)
15
+ puts "#{File.basename($0)}: #{message}"
16
+ exit 1
17
+ end
18
+
19
+ $source_directories = []
20
+ $library_filenames = []
21
+ $extra_arguments = []
22
+
23
+ OptionParser.new do |parser|
24
+ parser.banner = "Usage: fcshc MAIN [SRCDIR|LIB]... -o OUTPUT"
25
+
26
+ parser.on("--halo", "Use the Halo theme") do
27
+ if ENV["FLEX_HOME"]
28
+ $extra_arguments << "-theme=" +
29
+ File.join(ENV["FLEX_HOME"], *%w(frameworks themes Halo halo.swc))
30
+ else
31
+ die "must set $FLEX_HOME to use --halo option"
32
+ end
33
+ end
34
+
35
+ parser.on("-o", "--output FILENAME", "Write SWF to FILENAME") do |value|
36
+ $output_filename = File.expand_path(value)
37
+ end
38
+
39
+ parser.on("-3", "Use -compatibility-version=3") do |value|
40
+ $extra_arguments << "-compatibility-version=3"
41
+ end
42
+
43
+ parser.on("-X EXTRA-ARGUMENT", "Pass EXTRA-ARGUMENT to mxmlc") do |value|
44
+ $extra_arguments << value
45
+ end
46
+
47
+ parser.on("-v", "--verbose", "Print mxmlc command line") do
48
+ $verbose = true
49
+ end
50
+ end.parse!
51
+
52
+ for name in ARGV
53
+ if not File.exists? name
54
+ die "no such file or directory: #{name}"
55
+ elsif File.directory? name
56
+ $source_directories << File.expand_path(name)
57
+ 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)
60
+ elsif %w(.swc).include? File.extname(name)
61
+ $library_filenames << File.expand_path(name)
62
+ else
63
+ die "don't know what to do with file: #{name}"
64
+ end
65
+ end
66
+
67
+ if $source_filename == nil
68
+ die "missing source file to compile"
69
+ end
70
+
71
+ if $output_filename == nil
72
+ $source_filename.sub(/\.(as|mxml)$/, ".swf").tap do |filename|
73
+ local_filename = File.basename(filename)
74
+ $output_filename = File.expand_path(local_filename)
75
+ end
76
+ end
77
+
78
+ $fcshd_arguments = ["mxmlc #$source_filename -output=#$output_filename"]
79
+
80
+ for directory in $source_directories
81
+ $fcshd_arguments << "-compiler.source-path+=#{directory}"
82
+ end
83
+
84
+ for filename in $library_filenames
85
+ $fcshd_arguments << "-compiler.library-path+=#{filename}"
86
+ end
87
+
88
+ $fcshd_arguments.concat($extra_arguments)
89
+
90
+ begin
91
+ host, port = "localhost", 34345
92
+ socket = TCPSocket.new(host, port)
93
+ rescue Errno::ECONNREFUSED
94
+ die "Could not connect to fcshd at #{host}:#{port}."
95
+ end
96
+
97
+ basedir = File.join(File.expand_path("."), "")
98
+
99
+ fcshd_command = $fcshd_arguments.join(" ")
100
+ warn fcshd_command.gsub(basedir, "") if $verbose
101
+ socket.puts fcshd_command
102
+
103
+ compiler_output = ""
104
+ socket.each_line do |line|
105
+ case line
106
+ when /^fcshd: /
107
+ warn line.chomp
108
+ else
109
+ compiler_output << line
110
+ end
111
+ end
112
+
113
+ output = FCSHD::CompilerOutput[compiler_output, basedir]
114
+ output.write! FCSHD::CompilerOutputWriter.new(STDOUT, basedir)
115
+
116
+ exit 1 if not output.succeeded?
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ begin
4
+ require "fcshd"
5
+ rescue LoadError
6
+ require "pathname"
7
+ $: << File.expand_path("../../lib", Pathname.new(__FILE__).realpath)
8
+ require "fcshd"
9
+ end
10
+
11
+ logger = FCSHD::Logger.new(STDERR)
12
+ compiler = FCSHD::Compiler.new(logger)
13
+ compiler.start!
14
+
15
+ Thread.abort_on_exception = true
16
+
17
+ FCSHD_PORT = 34345
18
+
19
+ begin
20
+ logger.log "Listening to port #{FCSHD_PORT}."
21
+ FCSHD::Server.new(FCSHD_PORT, compiler, logger).run!
22
+ rescue Interrupt
23
+ logger.log "Exiting."
24
+ end
@@ -0,0 +1,19 @@
1
+ require "./lib/fcshd/version"
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "fcshd"
5
+ gem.summary = "Usable CLI for the Adobe Flex compiler shell (fcsh)"
6
+ gem.description = <<'^D'
7
+ By using a client-server architecture, we are able to make the Adobe Flex
8
+ compiler run fast while still being usable in command-line environments.
9
+ In practice, you start the `fcshd' server, and are then able to use the
10
+ client program `fcshc' as a faster and more usable replacement for `mxmlc'.
11
+ ^D
12
+ gem.version = FCSHD::VERSION
13
+ gem.author = "Daniel Brockman"
14
+ gem.email = "daniel@gointeractive.se"
15
+ gem.date = Time.now.utc.strftime("%Y-%m-%d")
16
+ gem.homepage = "http://github.com/dbrock/fcshd"
17
+ gem.files = `git ls-files`.lines.map(&:chomp)
18
+ gem.executables = %w"fcshd fcshc"
19
+ end
@@ -0,0 +1,8 @@
1
+ require "fcshd/compiler-output-writer"
2
+ require "fcshd/compiler-output"
3
+ require "fcshd/compiler"
4
+ require "fcshd/logger"
5
+ require "fcshd/problem"
6
+ require "fcshd/server"
7
+ require "fcshd/source-location"
8
+ require "fcshd/version"
@@ -0,0 +1,19 @@
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
@@ -0,0 +1,91 @@
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
@@ -0,0 +1,145 @@
1
+ require "find"
2
+
3
+ module FCSHD
4
+ class Compiler
5
+ FLEX_HOME = ENV["FLEX_HOME"]
6
+
7
+ def self.flex_path(*components)
8
+ File.join(FLEX_HOME, *components)
9
+ end
10
+
11
+ def self.standard_fcsh_executable
12
+ FLEX_HOME ? flex_path("bin", "fcsh") : "fcsh"
13
+ end
14
+
15
+ def self.standard_source_directory_root
16
+ flex_path("frameworks", "projects")
17
+ end
18
+
19
+ def self.barename(filename)
20
+ File.basename(filename).sub(/\..*/, "")
21
+ end
22
+
23
+ def self.find_standard_component(name)
24
+ if FLEX_HOME
25
+ Find.find(standard_source_directory_root) do |filename|
26
+ if barename(filename) == name
27
+ break File.dirname(filename).
28
+ sub(%r{.+/src/}, "").gsub("/", ".")
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ FCSH_EXECUTABLE = ENV["FCSH"] || standard_fcsh_executable
35
+
36
+ def initialize(logger)
37
+ @logger = logger
38
+ @output_buffer = ""
39
+ end
40
+
41
+ def start!
42
+ start_fcsh_process!
43
+ parse_fcsh_boilerplate!
44
+ @logger.log "Started Flex #@flex_version compiler shell."
45
+ rescue PromptNotFound => error
46
+ @logger.error "Could not find fcsh prompt:"
47
+ @logger.error @logger.format_command(FCSH_EXECUTABLE, error.message)
48
+ @logger.log "Please set $FLEX_HOME or $FCSH." if
49
+ error.message.include? "command not found"
50
+ @logger.exit
51
+ end
52
+
53
+ def compile! command, frontend
54
+ @command, @frontend = command, frontend
55
+
56
+ if have_command_id?
57
+ recompile!
58
+ else
59
+ compile_new!
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def start_fcsh_process!
66
+ stop_fcsh_process!
67
+ @fcsh_process = IO.popen("#{FCSH_EXECUTABLE} 2>&1", "r+")
68
+ read_fcsh_output!
69
+ end
70
+
71
+ def stop_fcsh_process!
72
+ @fcsh_process.close if @fcsh_process
73
+ @fcsh_process = nil
74
+ @command_ids = {}
75
+ end
76
+
77
+ def parse_fcsh_boilerplate!
78
+ case @output
79
+ when /Version (\S+)/
80
+ @flex_version = $1
81
+ else
82
+ @flex_version = "(unknown version)"
83
+ end
84
+ end
85
+
86
+ def compile_new!
87
+ @frontend.puts "fcshd: Compiling from scratch..."
88
+ @frontend.flush
89
+ send_fcsh_command! @command
90
+ parse_compilation_output!
91
+ ensure
92
+ if not have_command_id?
93
+ @logger.error "Could not determine compilation ID:"
94
+ @logger.error @logger.format_command("(fcsh) #@command", @output)
95
+ end
96
+ end
97
+
98
+ def recompile!
99
+ send_fcsh_command! "compile #{command_id}"
100
+ parse_compilation_output!
101
+ end
102
+
103
+ def command_id
104
+ @command_ids[@command]
105
+ end
106
+
107
+ def command_id= id
108
+ @command_ids[@command] = id
109
+ end
110
+
111
+ def have_command_id?
112
+ @command_ids.include? @command
113
+ end
114
+
115
+ def parse_compilation_output!
116
+ for line in @output.lines
117
+ case line
118
+ when /^fcsh: Assigned (\d+) as the compile target id$/
119
+ self.command_id = $1
120
+ else
121
+ @frontend.puts(line)
122
+ @logger.log_raw(line) if line =~ /^fcsh: /
123
+ end
124
+ end
125
+ end
126
+
127
+ def send_fcsh_command! command
128
+ @logger.log_raw("> #{command}")
129
+ @fcsh_process.puts(command)
130
+ read_fcsh_output!
131
+ end
132
+
133
+ FCSH_PROMPT = "\n(fcsh) "
134
+ class PromptNotFound < Exception ; end
135
+
136
+ def read_fcsh_output!
137
+ @output_buffer << @fcsh_process.readpartial(256) until
138
+ @output_buffer.include? FCSH_PROMPT
139
+ @output, @output_buffer =
140
+ @output_buffer.split(FCSH_PROMPT, 2)
141
+ rescue EOFError
142
+ raise PromptNotFound, @output_buffer
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,41 @@
1
+ module FCSHD
2
+ class Logger
3
+ def initialize(output)
4
+ @stderr = output
5
+ end
6
+
7
+ def log_raw(message)
8
+ @stderr.puts message
9
+ end
10
+
11
+ def log(message)
12
+ for line in message.lines
13
+ log_raw "#{program_name}: #{line.chomp}"
14
+ end
15
+ end
16
+
17
+ def program_name
18
+ File.basename($0)
19
+ end
20
+
21
+ def error(message)
22
+ for line in message.lines
23
+ log "error: #{line.chomp}"
24
+ end
25
+ end
26
+
27
+ def die(message)
28
+ error message ; exit
29
+ end
30
+
31
+ def exit(code=1)
32
+ Kernel.exit code
33
+ end
34
+
35
+ def format_command(command, output)
36
+ ["$ #{command}", *output.lines].
37
+ map { |line| " #{line.chomp}" }.
38
+ join("\n")
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,153 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ 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
+ Compiler.find_standard_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
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,34 @@
1
+ require "socket"
2
+
3
+ module FCSHD
4
+ class Server
5
+ def initialize(port, compiler, logger)
6
+ @server = TCPServer.new("localhost", port)
7
+ @compiler = compiler
8
+ @logger = logger
9
+ end
10
+
11
+ def run!
12
+ loop do
13
+ Thread.start(@server.accept) do |socket|
14
+ Client.new(socket, @compiler).run!
15
+ end
16
+ end
17
+ end
18
+
19
+ class Client < Struct.new(:socket, :compiler)
20
+ def run!
21
+ case command = socket.gets
22
+ when /^mxmlc /
23
+ compiler.compile! command, socket
24
+ else
25
+ sockets.puts "fcshd: Unrecognized command: #{command}"
26
+ end
27
+ rescue Errno::EPIPE
28
+ logger.log "Broken pipe."
29
+ ensure
30
+ socket.close
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
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
9
+ end
10
+
11
+ def relative_filename
12
+ if basedir
13
+ filename.sub(/^#{Regexp.quote(basedir)}/, "")
14
+ else
15
+ filename
16
+ end
17
+ 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
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ unless defined? FCSHD::VERSION
2
+ module FCSHD
3
+ VERSION = "0.1"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fcshd
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Daniel Brockman
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-08-31 00:00:00 Z
18
+ dependencies: []
19
+
20
+ description: |
21
+ By using a client-server architecture, we are able to make the Adobe Flex
22
+ compiler run fast while still being usable in command-line environments.
23
+ In practice, you start the `fcshd' server, and are then able to use the
24
+ client program `fcshc' as a faster and more usable replacement for `mxmlc'.
25
+
26
+ email: daniel@gointeractive.se
27
+ executables:
28
+ - fcshd
29
+ - fcshc
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - .gitignore
36
+ - .rvmrc
37
+ - Gemfile
38
+ - Gemfile.lock
39
+ - bin/fcshc
40
+ - bin/fcshd
41
+ - fcshd.gemspec
42
+ - lib/fcshd.rb
43
+ - lib/fcshd/compiler-output-writer.rb
44
+ - lib/fcshd/compiler-output.rb
45
+ - lib/fcshd/compiler.rb
46
+ - lib/fcshd/logger.rb
47
+ - lib/fcshd/problem.rb
48
+ - lib/fcshd/server.rb
49
+ - lib/fcshd/source-location.rb
50
+ - lib/fcshd/version.rb
51
+ homepage: http://github.com/dbrock/fcshd
52
+ licenses: []
53
+
54
+ post_install_message:
55
+ rdoc_options: []
56
+
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ requirements: []
78
+
79
+ rubyforge_project:
80
+ rubygems_version: 1.8.8
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Usable CLI for the Adobe Flex compiler shell (fcsh)
84
+ test_files: []
85
+