Permalink
Browse files

fixing problem with build system and paths

  • Loading branch information...
1 parent 3dbf0e3 commit 5078a45cb44c1c40decbade8260f02548112e516 @lucasdupin committed Jun 12, 2011
Showing with 208 additions and 8 deletions.
  1. +2 −1 Actionscript3.sublime-build
  2. +2 −7 bin/Rakefile
  3. +204 −0 exec_as3.py
View
3 Actionscript3.sublime-build
@@ -3,5 +3,6 @@
"working_dir": "${project_path:${file_path}}",
"file_regex": "(.*?)\\(([0-9]*)\\): col: ([0-9]*) Error: ",
"selector": "source.actionscript.3,source.yaml",
- "shell": true
+ "shell": true,
+ "target": "exec_as3"
}
View
9 bin/Rakefile
@@ -184,17 +184,12 @@ end
# Making sure the config file exists
unless File.exists?(current_path + "/build.yaml")
puts "Could not find buil.yaml at #{current_path + "/build.yaml"}"
- return
+ exit 1
end
-# Making sure the Flex SDK is in the path
-paths = ['~/.profile', '~/.bash_profile', "~/.bashrc"].map do |p|
- "source #{p} 2&>1; " if File.exists? File.expand_path(p)
-end
-ENV['PATH'] = `#{paths.join} echo $PATH`
if `/usr/bin/which fcsh`.empty?
puts "Could not find 'fcsh', is it in your PATH?"
puts "Your path is: #{ENV['PATH']}"
- return
+ exit 1
end
# ####################################################################
View
204 exec_as3.py
@@ -0,0 +1,204 @@
+import sublime, sublime_plugin
+import os, sys
+import thread
+import subprocess
+import functools
+
+class ProcessListener(object):
+ def on_data(self, proc, data):
+ pass
+
+ def on_finished(self, proc):
+ pass
+
+# Encapsulates subprocess.Popen, forwarding stdout to a supplied
+# ProcessListener (on a separate thread)
+class AsyncProcess(object):
+ def __init__(self, arg_list, env, listener,
+ # "path" is an option in build systems
+ path="",
+ # "shell" is an options in build systems
+ shell=False):
+
+ self.listener = listener
+ self.killed = False
+
+ # Hide the console window on Windows
+ startupinfo = None
+ if os.name == "nt":
+ startupinfo = subprocess.STARTUPINFO()
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+
+ # Set temporary PATH to locate executable in arg_list
+ if path:
+ old_path = os.environ["PATH"]
+ # The user decides in the build system whether he wants to append $PATH
+ # or tuck it at the front: "$PATH;C:\\new\\path", "C:\\new\\path;$PATH"
+ os.environ["PATH"] = os.path.expandvars().encode(sys.getfilesystemencoding())
+
+ for p in ["~/.bashrc", "~/.profile", "~/.bash_profile"]:
+ up = os.path.expanduser(p)
+ if os.path.exists(up):
+ os.system("source %s 2&>1; echo $PATH > /tmp/path" % up)
+ break
+ os.environ['PATH'] = open("/tmp/path").read()
+
+ proc_env = os.environ.copy()
+ proc_env.update(env)
+ for k, v in proc_env.iteritems():
+ proc_env[k] = os.path.expandvars(v).encode(sys.getfilesystemencoding())
+
+ self.proc = subprocess.Popen(arg_list, stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, startupinfo=startupinfo, env=proc_env, shell=shell)
+
+ if path:
+ os.environ["PATH"] = old_path
+
+ if self.proc.stdout:
+ thread.start_new_thread(self.read_stdout, ())
+
+ if self.proc.stderr:
+ thread.start_new_thread(self.read_stderr, ())
+
+ def kill(self):
+ if not self.killed:
+ self.killed = True
+ self.proc.kill()
+ self.listener = None
+
+ def poll(self):
+ return self.proc.poll() == None
+
+ def read_stdout(self):
+ while True:
+ data = os.read(self.proc.stdout.fileno(), 2**15)
+
+ if data != "":
+ if self.listener:
+ self.listener.on_data(self, data)
+ else:
+ self.proc.stdout.close()
+ if self.listener:
+ self.listener.on_finished(self)
+ break
+
+ def read_stderr(self):
+ while True:
+ data = os.read(self.proc.stderr.fileno(), 2**15)
+
+ if data != "":
+ if self.listener:
+ self.listener.on_data(self, data)
+ else:
+ self.proc.stderr.close()
+ break
+
+class ExecAs3Command(sublime_plugin.WindowCommand, ProcessListener):
+ def run(self, cmd = [], file_regex = "", line_regex = "", working_dir = "",
+ encoding = "utf-8", env = {}, quiet = False, kill = False,
+ # Catches "path" and "shell"
+ **kwargs):
+
+ if kill:
+ if self.proc:
+ self.proc.kill()
+ self.proc = None
+ self.append_data(None, "[Cancelled]")
+ return
+
+ if not hasattr(self, 'output_view'):
+ # Try not to call get_output_panel until the regexes are assigned
+ self.output_view = self.window.get_output_panel("exec")
+
+ self.output_view.settings().set("result_file_regex", file_regex)
+ self.output_view.settings().set("result_line_regex", line_regex)
+ self.output_view.settings().set("result_base_dir", working_dir)
+
+ # Call get_output_panel a second time after assigning the above
+ # settings, so that it'll be picked up as a result buffer
+ self.window.get_output_panel("exec")
+
+ self.encoding = encoding
+ self.quiet = quiet
+
+ self.proc = None
+ if not self.quiet:
+ print "Running " + " ".join(cmd)
+
+ self.window.run_command("show_panel", {"panel": "output.exec"})
+
+ merged_env = env.copy()
+ if self.window.active_view():
+ user_env = self.window.active_view().settings().get('build_env')
+ if user_env:
+ merged_env.update(user_env)
+
+ # Change to the working dir, rather than spawning the process with it,
+ # so that emitted working dir relative path names make sense
+ if working_dir != "":
+ os.chdir(working_dir)
+
+ err_type = OSError
+ if os.name == "nt":
+ err_type = WindowsError
+
+ try:
+ # Forward kwargs to AsyncProcess
+ self.proc = AsyncProcess(cmd, merged_env, self, **kwargs)
+ except err_type as e:
+ self.append_data(None, str(e) + "\n")
+ if not self.quiet:
+ self.append_data(None, "[Finished]")
+
+ def is_enabled(self, kill = False):
+ if kill:
+ return hasattr(self, 'proc') and self.proc and self.proc.poll()
+ else:
+ return True
+
+ def append_data(self, proc, data):
+ if proc != self.proc:
+ # a second call to exec has been made before the first one
+ # finished, ignore it instead of intermingling the output.
+ if proc:
+ proc.kill()
+ return
+
+ try:
+ str = data.decode(self.encoding)
+ except:
+ str = "[Decode error - output not " + self.encoding + "]"
+ proc = None
+
+ # Normalize newlines, Sublime Text always uses a single \n separator
+ # in memory.
+ str = str.replace('\r\n', '\n').replace('\r', '\n')
+
+ selection_was_at_end = (len(self.output_view.sel()) == 1
+ and self.output_view.sel()[0]
+ == sublime.Region(self.output_view.size()))
+ self.output_view.set_read_only(False)
+ edit = self.output_view.begin_edit()
+ self.output_view.insert(edit, self.output_view.size(), str)
+ if selection_was_at_end:
+ self.output_view.show(self.output_view.size())
+ self.output_view.end_edit(edit)
+ self.output_view.set_read_only(True)
+
+ def finish(self, proc):
+ if not self.quiet:
+ self.append_data(proc, "[Finished]")
+ if proc != self.proc:
+ return
+
+ # Set the selection to the start, so that next_result will work as expected
+ edit = self.output_view.begin_edit()
+ self.output_view.sel().clear()
+ self.output_view.sel().add(sublime.Region(0))
+ self.output_view.end_edit(edit)
+
+ def on_data(self, proc, data):
+ sublime.set_timeout(functools.partial(self.append_data, proc, data), 0)
+
+ def on_finished(self, proc):
+ sublime.set_timeout(functools.partial(self.finish, proc), 0)

0 comments on commit 5078a45

Please sign in to comment.