<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -7,7 +7,7 @@ require ENV['TM_SUPPORT_PATH'] + '/lib/textmate'
 require ENV['TM_SUPPORT_PATH'] + '/lib/tm/process'
 
 require File.expand_path(File.dirname(__FILE__)) + '/../lib/add_lib'
-
+require 'find'
 require 'fm/flex_mate'
 require 'fm/sdk'
 require 'fm/compiler'</diff>
      <filename>Support/bin/build.rb</filename>
    </modified>
    <modified>
      <diff>@@ -45,7 +45,8 @@ module SourceTools
         path = truncate_to_src(path)
         path = path.gsub(/\.(as|mxml)$/,'').gsub( &quot;/&quot;, &quot;.&quot;).sub(/^\./,'')
 
-        if path =~ /\.#{word}$/
+        # if path =~ /\.#{word}$/
+        if path =~ /\b#{word}$/
           best_paths &lt;&lt; path
         else
           package_paths &lt;&lt; path
@@ -59,8 +60,8 @@ module SourceTools
 
   end
 
-  # Loads all paths stored in the bundle lookup that have a filename which
-  # contains the requested word.
+  # Loads all paths stored in the bundle lookup dictionary that have a filename
+  # which contains the requested word.
   #
   def self.search_bundle_paths(word)
 
@@ -189,4 +190,287 @@ module SourceTools
     
   end
   
+  # Searches the current project for as and mxml files and returns them in an 
+  # array. All collected file paths are truncated to their source directory.
+  #
+  def self.list_all_class_files
+    
+    dirs = []
+    excludes = ['.svn', '.git']
+    types = /\.(as|mxml)/
+    classes = []
+    
+    #limit the search to the common src dirs found within the proj root.
+    pr = ENV['TM_PROJECT_DIRECTORY']
+    common_src_dirs.each do |d| 
+      dirs &lt;&lt; &quot;#{pr}/#{d}&quot; if File.exist?(&quot;#{pr}/#{d}&quot;)
+    end
+    #if no src dirs are recognised scan the whole proj.
+    dirs &lt;&lt; pr if dirs.empty?
+    
+    for dir in dirs
+        Find.find(dir) do |path|
+
+            if FileTest.directory?(path)
+              if excludes.include?(File.basename(path))
+                  Find.prune
+              else
+                  next
+              end
+            elsif File.extname(path) =~ types
+              classes &lt;&lt; truncate_to_src(path)
+            end
+        end
+    end
+    
+    classes.uniq
+    
+  end
+  
+  def self.list_all_classes
+    cf = list_all_class_files
+    c = []
+    cf.each { |e| c &lt;&lt; e.gsub('/','.').sub(/.(as|mxml)$/,'') }
+    c
+  end
+  
+end
+
+if __FILE__ == $0
+
+# Boolean to control whether or not UI Dialog boxes are presented during testing.
+$run_ui_tests = false;
+
+if $run_ui_tests
+  print &quot;Select first element from each Menu for the tests to pass.\n\n&quot;   
+else
+  print &quot;WARNING: Interactive UI Tests were skipped.\n\n&quot; 
+end
+  
+require &quot;test/unit&quot;
+
+class TestSourceTools &lt; Test::Unit::TestCase
+  
+  # =========
+  # = Setup =
+  # =========
+  
+  def custom_src_dirs
+    &quot;foo:bar:baz&quot;
+  end
+
+  def default_src_dirs
+    &quot;src:lib:source:test&quot;
+  end
+  
+  def clean_env
+    ENV['TM_AS3_USUAL_SRC_DIRS'] = nil
+  end  
+  
+  def run_ui_tests
+    $run_ui_tests
+  end
+  
+  # =========
+  # = Tests =
+  # =========
+   
+  def test_common_src_dir_list
+    clean_env
+    
+    assert_equal(default_src_dirs, SourceTools.common_src_dir_list)
+    
+    ENV['TM_AS3_USUAL_SRC_DIRS'] = custom_src_dirs
+    
+    assert_equal(custom_src_dirs, SourceTools.common_src_dir_list)
+    
+  end
+
+  def test_common_src_dirs
+    clean_env
+    
+    assert_equal('src', SourceTools.common_src_dirs[0])
+    
+    ENV['TM_AS3_USUAL_SRC_DIRS'] = custom_src_dirs
+    
+    assert_equal('foo', SourceTools.common_src_dirs[0])
+  end
+  
+  def test_search_project_paths
+    
+    clean_env
+
+    require ENV['TM_SUPPORT_PATH'] + '/lib/textmate'
+
+    ENV['TM_AS3_USUAL_SRC_DIRS'] = 'intrinsic'
+    
+    r = SourceTools.search_project_paths('Mov')
+
+    assert_equal('flash.display.MovieClip', r[:partial_matches].to_s)
+    assert_equal('', r[:exact_matches].to_s)
+    
+    r = SourceTools.search_project_paths('MovieClip')
+
+    assert_equal('', r[:partial_matches].to_s)
+    assert_equal('flash.display.MovieClip', r[:exact_matches].to_s)
+
+    r = SourceTools.search_project_paths('Event')
+
+    assert_equal('flash.events.EventDispatcher|flash.events.EventPhase', r[:partial_matches].join('|'))    
+    assert_equal('flash.events.Event', r[:exact_matches].to_s)
+
+    r = SourceTools.search_project_paths('Math')
+    
+    assert_equal('', r[:partial_matches].to_s)
+    assert_equal('Math', r[:exact_matches].to_s)
+
+    r = SourceTools.search_project_paths('E')
+
+    assert_equal(9, r[:partial_matches].length)
+    assert_equal('', r[:exact_matches].to_s)
+    
+  end
+  
+  def test_search_bundle_paths
+
+    clean_env
+    
+    r = SourceTools.search_bundle_paths('Mov')
+
+    assert_equal('flash.display.MovieClip|mx.core.MovieClipAsset|mx.core.MovieClipLoaderAsset|mx.effects.Move|mx.effects.effectClasses.MoveInstance|mx.events.MoveEvent', r[:partial_matches].join('|'))
+    assert_equal('', r[:exact_matches].to_s)
+    
+    r = SourceTools.search_bundle_paths('MovieClip')
+
+    assert_equal('mx.core.MovieClipAsset|mx.core.MovieClipLoaderAsset', r[:partial_matches].join('|'))
+    assert_equal('flash.display.MovieClip', r[:exact_matches].to_s)
+
+    r = SourceTools.search_bundle_paths('Event')
+
+    assert_equal('flash.events.EventDispatcher|flash.events.EventPhase|mx.core.EventPriority', r[:partial_matches].join('|'))    
+    assert_equal('flash.events.Event', r[:exact_matches].to_s)
+
+    r = SourceTools.search_bundle_paths('Math')
+    
+    assert_equal('', r[:partial_matches].to_s)
+    assert_equal('Math', r[:exact_matches].to_s)
+
+    r = SourceTools.search_bundle_paths('E')
+
+    assert_equal(23, r[:partial_matches].length)
+    assert_equal('', r[:exact_matches].to_s)
+    
+  end
+  
+  def test_search_all_paths
+
+    clean_env
+    
+    ENV['TM_AS3_USUAL_SRC_DIRS'] = 'intrinsic'
+    
+    r = SourceTools.search_all_paths('Mov')
+
+    assert_equal('flash.display.MovieClip|mx.core.MovieClipAsset|mx.core.MovieClipLoaderAsset|mx.effects.Move|mx.effects.effectClasses.MoveInstance|mx.events.MoveEvent', r[:partial_matches].join('|'))
+    assert_equal('', r[:exact_matches].to_s)
+    
+    r = SourceTools.search_all_paths('MovieClip')
+
+    assert_equal('mx.core.MovieClipAsset|mx.core.MovieClipLoaderAsset', r[:partial_matches].join('|'))
+    assert_equal('flash.display.MovieClip', r[:exact_matches].to_s)
+
+    r = SourceTools.search_all_paths('Event')
+
+    assert_equal('flash.events.EventDispatcher|flash.events.EventPhase|mx.core.EventPriority', r[:partial_matches].join('|'))    
+    assert_equal('flash.events.Event', r[:exact_matches].to_s)
+
+    r = SourceTools.search_all_paths('Math')
+    
+    assert_equal('', r[:partial_matches].to_s)
+    assert_equal('Math', r[:exact_matches].to_s)
+
+    r = SourceTools.search_all_paths('E')
+
+    assert_equal(23, r[:partial_matches].length)
+    assert_equal('', r[:exact_matches].to_s)
+    
+  end
+    
+  def test_truncate_to_src
+    clean_env
+    
+    p = 'a/b/src/com'    
+    assert_equal('com', SourceTools.truncate_to_src(p))
+    
+    p = '/a/b/source/c/src/test/org/helvector/io'
+    assert_equal('org/helvector/io', SourceTools.truncate_to_src(p))    
+
+    p = '/a/b/source/org/helvector/io'
+    assert_equal('org/helvector/io', SourceTools.truncate_to_src(p))    
+    
+  end
+  
+  def test_find_package
+
+    clean_env
+
+    require ENV['TM_SUPPORT_PATH'] + '/lib/textmate'
+    require ENV['TM_SUPPORT_PATH'] + '/lib/ui'
+
+    ENV['TM_AS3_USUAL_SRC_DIRS'] = 'intrinsic'
+
+    assert_equal('VerifyError', SourceTools.find_package('VerifyError'))
+    assert_equal('flash.data.SQLSchemaResult', SourceTools.find_package('SQLSchemaResult'))
+    
+    # When you get the UI menu select the first item in the list.
+    if run_ui_tests
+      assert_equal('flash.display.MovieClip', SourceTools.find_package('Mov'))
+      assert_equal('flash.data.SQLCollationType', SourceTools.find_package('SQL'))      
+    end
+    
+  end
+  
+  def test_list_package
+    
+    clean_env
+
+    p = ENV['TM_PROJECT_DIRECTORY'] + '/Support/data/completions/intrinsic/flash/display'
+    c = SourceTools.list_package(p)
+    
+    assert_equal(c.include?('MovieClip'), true)
+    assert_equal(c.length, 33)
+    
+    p = ENV['TM_PROJECT_DIRECTORY'] + '/Support/data/completions/intrinsic/flash/accessibility'
+    c = SourceTools.list_package(p)
+    
+    assert_equal(c.length, 2)
+  end
+  
+  def test_list_all_class_files
+    clean_env
+    
+    require 'find'
+    
+    ENV['TM_AS3_USUAL_SRC_DIRS'] = 'intrinsic'
+
+    c = SourceTools.list_all_class_files
+    
+    assert_equal(c.include?('Boolean.as'), true)
+    assert_equal(c.length, 213)
+  end
+  
+  def test_list_all_classes
+    clean_env
+    
+    require 'find'
+    
+    ENV['TM_AS3_USUAL_SRC_DIRS'] = 'intrinsic'
+    
+    c = SourceTools.list_all_classes
+    
+    assert_equal(c.include?('Boolean'), true)
+    assert_equal(c.length, 213)
+    
+  end
 end
+
+end
\ No newline at end of file</diff>
      <filename>Support/lib/as3/source_tools.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,22 +9,18 @@ module FlexMate
       FlexMate::SDK.add_flex_bin_to_path
     end
 
-    # Run mxmlc to compile a swf adapting to the current environment as
+    # Run mxmlc or compc to compile a swf adapting to the current environment as
     # necessary.
     #
     def build
       
-      bin = 'mxmlc'
-      
-      TextMate.require_cmd(bin)
-      
       s = FlexMate::Settings.new
       
-      cmd = MxmlcCommand.new
-      cmd.file_specs = s.file_specs
-      cmd.o = s.flex_output
-      
-      init_html(bin,cmd)
+      cmd = build_tool(s)
+
+      TextMate.require_cmd(cmd.name)
+            
+      init_html(cmd)
       
       exhaust = get_exhaust
 
@@ -33,7 +29,14 @@ module FlexMate
       end
 
       STDOUT &lt;&lt; exhaust.complete
-
+      
+      STDOUT &lt;&lt; '&lt;br/&gt;&lt;br/&gt;&lt;div class=&quot;raw_out&quot;&gt;&lt;span class=&quot;showhide&quot;&gt;'
+      STDOUT &lt;&lt; &quot;&lt;a href=\&quot;javascript:hideElement('raw_out')\&quot; id='raw_out_h' style='display: none;'&gt;&amp;#x25BC; Hide Raw Output&lt;/a&gt;&quot;
+      STDOUT &lt;&lt; &quot;&lt;a href=\&quot;javascript:showElement('raw_out')\&quot; id='raw_out_s' style=''&gt;&amp;#x25B6; Show Raw Output&lt;/a&gt;&quot;
+      STDOUT &lt;&lt; '&lt;/span&gt;&lt;/div&gt;'
+      STDOUT &lt;&lt; '&lt;div class=&quot;inner&quot; id=&quot;raw_out_b&quot; style=&quot;display: none;&quot;&gt;&lt;br/&gt;'
+      STDOUT &lt;&lt; &quot;&lt;code&gt;#{exhaust.input.to_s}&lt;/code&gt;&lt;br/&gt;&quot;      
+      
       html_footer
 
     end
@@ -42,17 +45,16 @@ module FlexMate
     
     # Print initial html header.
     #
-    def init_html(bin,cmd)
+    def init_html(cmd)
       
       require ENV['TM_SUPPORT_PATH'] + '/lib/web_preview'
 
       puts html_head( :window_title =&gt; &quot;ActionScript 3 Build Command&quot;,
-                      :page_title =&gt; &quot;Build (#{bin})&quot;,
+                      :page_title =&gt; &quot;Build (#{cmd.name})&quot;,
                       :sub_title =&gt; cmd.file_specs_name )
 
       puts &quot;&lt;h2&gt;Building...&lt;/h2&gt;&quot;
-      puts &quot;&lt;p&gt;&lt;pre&gt;-file-specs=#{cmd.file_specs}&quot;
-      puts &quot;-o=#{cmd.o}&lt;/pre&gt;&lt;/p&gt;&quot;      
+      puts &quot;&lt;p&gt;&lt;pre&gt;#{cmd.to_s}&lt;/pre&gt;&lt;/p&gt;&quot;
       
     end
     
@@ -62,6 +64,13 @@ module FlexMate
       require 'fm/mxmlc_exhaust'
       MxmlcExhaust.new
     end
+    
+    # Create the command responsible for compiling the source.
+    #
+    def build_tool(settings)
+        return CompcCommand.new(settings) if settings.is_swc
+        return MxmlcCommand.new(settings)
+    end
 
   end
   
@@ -79,27 +88,25 @@ module FlexMate
       TextMate.require_cmd(bin)
       
       s = FlexMate::Settings.new
-			
+      
       ENV['TM_FLEX_FILE_SPECS'] = s.file_specs
       ENV['TM_FLEX_OUTPUT'] = s.flex_output
-
-			#WARN: Access s.flex_output after this point will fail. This is because 
-			#      settings expects TM_FLEX_OUTPUT to be relative to the project root
-			#      + we've just set it to a full path.
+      
+      #WARN: Accessing s.flex_output after this point will fail. This is because 
+      #      settings expects TM_FLEX_OUTPUT to be relative to the project root
+      #      + we've just set it to a full path.
       
       FlexMate.required_settings({ :files =&gt; ['TM_FLEX_FILE_SPECS'],
                                    :evars =&gt; ['TM_FLEX_OUTPUT'] })
       
-      cmd = MxmlcCommand.new
-      cmd.file_specs = ENV['TM_FLEX_FILE_SPECS']
-      cmd.o = ENV['TM_FLEX_OUTPUT']
+      cmd = build_tool(s)
       
       fcsh = e_sh(ENV['TM_FLEX_PATH'] + '/bin/fcsh')
-
+      
       #Make sure there are no spaces for fcsh to trip up on.
       FlexMate.check_valid_paths([cmd.file_specs,cmd.o,fcsh])
       
-      init_html(bin,cmd)
+      init_html(cmd)
       
       `osascript -e 'tell application &quot;Terminal&quot; to activate'` unless ENV['TM_FLEX_BACKGROUND_TERMINAL']
       `#{e_sh ENV['TM_BUNDLE_SUPPORT']}/lib/fcsh_terminal \&quot;#{fcsh}\&quot; \&quot;#{cmd.line}\&quot; &gt;/dev/null;`
@@ -109,22 +116,58 @@ module FlexMate
     end
     
   end
+
 end
 
-# Object to encapsulate a mxmlc command with arguments.
+# Object to encapsulate a mxmlc command and its arguments.
 #
 class MxmlcCommand
   
-  attr_accessor :file_specs
-  attr_accessor :o
+  attr_reader :file_specs
+  attr_reader :o
+  attr_reader :name
+  
+  def initialize(settings)
+    @name = 'mxmlc'
+    @o = settings.flex_output
+    @file_specs = settings.file_specs
+  end
 
   def line
-    &quot;mxmlc -file-specs=#{e_sh file_specs} -o=#{e_sh o}&quot;
+    &quot;#{name} -file-specs=#{e_sh file_specs} -o=#{e_sh o}&quot;
   end
 
   def file_specs_name
     File.basename(file_specs)
   end
+  
+  def to_s
+    &quot;-file-specs=#{file_specs}\n-o=#{e_sh o}&quot;
+  end
+
+end
+
+# Object to encapsulate a compc command and its arguments.
+#
+class CompcCommand &lt; MxmlcCommand
+  
+  attr_reader :include_classes
+  attr_reader :source_path
+  
+  def initialize(settings)
+    super(settings)
+    @name = 'compc'
+    @include_classes = settings.list_classes
+    @source_path = settings.source_path
+  end  
+  
+  def line
+    &quot;#{name} -source-path+=#{e_sh source_path} -o=#{e_sh o} #{include_classes}&quot;
+  end
+  
+  def to_s
+    &quot;#{name} -source-path+=#{e_sh source_path} -o=#{e_sh o}\n-include-classes=#{include_classes}&quot;
+  end
 
 end
 </diff>
      <filename>Support/lib/fm/compiler.rb</filename>
    </modified>
    <modified>
      <diff>@@ -94,6 +94,19 @@ module FlexMate
       return false
     end
     
+    # A list of classes found in the project.
+    #
+    def list_classes
+      SourceTools.list_all_classes.join(' ')
+    end
+    
+    def source_path
+      pr = proj_root
+      SourceTools.common_src_dirs.each do |d| 
+        return &quot;#{pr}/#{d}&quot; if File.exist?(&quot;#{pr}/#{d}&quot;)
+      end  
+    end
+    
     protected
     
     # Where we have Project Directory but no TM_FLEX_FILE_SPECS set take a look</diff>
      <filename>Support/lib/fm/settings.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>8f11dc990b40dc2cf00bb03fa6945093cae1ff0a</id>
    </parent>
  </parents>
  <author>
    <name>Simon Gregory</name>
    <email>simon@helvector.org</email>
  </author>
  <url>http://github.com/simongregory/actionscript3-tmbundle/commit/3a76f54ae0fce6c4a23fd4666f5651448a631b85</url>
  <id>3a76f54ae0fce6c4a23fd4666f5651448a631b85</id>
  <committed-date>2009-11-07T13:07:44-08:00</committed-date>
  <authored-date>2009-11-07T13:07:44-08:00</authored-date>
  <message>&#8226; Initial work to compile using compc by specifying TM_FLEX_OUTPUT's suffix with .swc</message>
  <tree>935fff3c7c815d12ddbc601313225eb41115c492</tree>
  <committer>
    <name>Simon Gregory</name>
    <email>simon@helvector.org</email>
  </committer>
</commit>
