From a16b1483f5afd08417702c36765d474e13cd6a02 Mon Sep 17 00:00:00 2001 From: makc Date: Fri, 7 Jun 2013 20:07:48 +0200 Subject: [PATCH] in fact, let's wait for proper api with updates. also closes #6. --- ColtPlugin/PluginMain.cs | 99 ++++++++++++++++------------ ColtPlugin/Resources/en_US.resX | 6 -- ColtPlugin/Settings.cs | 12 ---- ColtPlugin/obj/Debug/ColtPlugin.dll | Bin 17920 -> 16896 bytes 4 files changed, 58 insertions(+), 59 deletions(-) diff --git a/ColtPlugin/PluginMain.cs b/ColtPlugin/PluginMain.cs index 3b95b8a..5b0932e 100644 --- a/ColtPlugin/PluginMain.cs +++ b/ColtPlugin/PluginMain.cs @@ -31,7 +31,6 @@ public class PluginMain : IPlugin private Settings settingObject; private ToolStripMenuItem menuItem; private ToolStripButton toolbarButton; - private Boolean active = false; private FileSystemWatcher watcher; private String pathToLog; private System.Timers.Timer timer; @@ -134,21 +133,8 @@ public void HandleEvent(Object sender, NotifyEvent e, HandlingPriority prority) Boolean as3projectIsOpen = (project != null) && (project.Language == "as3"); if (menuItem != null) menuItem.Enabled = as3projectIsOpen; if (toolbarButton != null) toolbarButton.Enabled = as3projectIsOpen; - // deactivate - active = false; - if (watcher != null) watcher.EnableRaisingEvents = false; - if (timer != null) { timer.Stop(); timer = null; } - } - else if (cmd == "ASCompletion.ClassPath") - { - // apparently project setting changes; reopen already opened COLT project - if (active && (settingObject.AlwaysOverwriteProjects || (MessageBox.Show( - LocaleHelper.GetString("SettingsChanged.DialogText"), - LocaleHelper.GetString("SettingsChanged.DialogTitle"), - MessageBoxButtons.YesNo) == DialogResult.Yes))) - { - OpenInCOLT(); - } + // modified or new project - reconnect in any case + ConnectToCOLT(); } else if (cmd == "ProjectManager.Menu") { @@ -163,7 +149,7 @@ public void HandleEvent(Object sender, NotifyEvent e, HandlingPriority prority) break; case EventType.FileSave: - if (active) ClearErrors(); + if (watcher.EnableRaisingEvents) ClearErrors(); break; case EventType.Keys: // shortcut pressed @@ -244,6 +230,7 @@ public void AddEventHandlers() private void CreateMenuItem(ToolStripMenuItem projectMenu) { menuItem = new ToolStripMenuItem(buttonText, GetImage("colt.png"), new EventHandler(OnClick), null); + menuItem.Enabled = false; projectMenu.DropDownItems.Add(menuItem); } @@ -269,7 +256,6 @@ private static Image GetImage(String imageName) private void OnClick(Object sender, System.EventArgs e) { - active = true; OpenInCOLT(); } @@ -332,35 +318,43 @@ private void OnTimerElapsed(object sender, EventArgs e) String incremental = "colt\\incremental"; String[] sources = PluginBase.CurrentProject.SourcePaths; - // [09.05.2013 17:26:54] Philippe Elsass: make sure you send the log line by line to the Output + // send the log line by line String[] messageLines = message.Split(new Char[] {'\r', '\n'}); bool hasErrors = false; foreach (String line in messageLines) if (line.Length > 0) { - // [08.05.2013 18:04:15] Philippe Elsass: you can also specify '-3' as 2nd parameter to the traces (error level) - // [08.05.2013 18:05:02] Philippe Elsass: so it will appear in red in the output and have an error icon in the results panel + int errorLevel = -3; if (line.Contains(incremental)) { - // carefully take the file name out - String file = line.Substring(0, line.IndexOf("): col")); - file = file.Substring(0, file.LastIndexOf("(")); - file = file.Substring(file.IndexOf(incremental) + incremental.Length + 1); - - // look for it in all source folders - for (int i = 0; i < sources.Length; i++) + try { - if (File.Exists(PluginBase.CurrentProject.GetAbsolutePath(Path.Combine(sources[i], file)))) + // carefully take the file name out + String file = line.Substring(0, line.IndexOf("): col")); + file = file.Substring(0, file.LastIndexOf("(")); + file = file.Substring(file.IndexOf(incremental) + incremental.Length + 1); + + // look for it in all source folders + for (int i = 0; i < sources.Length; i++) { - TraceManager.Add(line.Replace(incremental, sources[i]), -3); - hasErrors = true; - break; + if (File.Exists(PluginBase.CurrentProject.GetAbsolutePath(Path.Combine(sources[i], file)))) + { + TraceManager.Add(line.Replace(incremental, sources[i]), errorLevel); + hasErrors = true; + break; + } } } + + catch (Exception) + { + // unexpected format, send as is + TraceManager.Add(line, errorLevel); + } } else { // send as is - TraceManager.Add(line, -3); + TraceManager.Add(line, errorLevel); } } @@ -434,6 +428,33 @@ private string LineIndentPosition(ScintillaNet.ScintillaControl sci, int line) return ""; } + /// + /// Connects to COLT + /// + private void ConnectToCOLT(Boolean create = false) + { + // todo: clean up after previous connection + + // for now, shut down errors log watcher and its timer + watcher.EnableRaisingEvents = false; + if (timer != null) { timer.Stop(); timer = null; } + + // todo: if current project is opened in COLT - connect to it + + // for now, create the folder and subscribe to errors log updates + IProject project = PluginBase.CurrentProject; + + String coltFolderPath = project.GetAbsolutePath(settingObject.WorkingFolder); + if (create && !Directory.Exists(coltFolderPath)) Directory.CreateDirectory(coltFolderPath); + + if (Directory.Exists(coltFolderPath)) + { + pathToLog = Path.Combine(coltFolderPath, "compile_errors.log"); + watcher.Path = coltFolderPath; + watcher.EnableRaisingEvents = true; + } + } + /// /// Opens the project in COLT /// @@ -468,15 +489,11 @@ private void OpenInCOLT() // Create COLT subfolder if does not exist yet - String coltFolderPath = project.GetAbsolutePath(settingObject.WorkingFolder); - if (!Directory.Exists(coltFolderPath)) Directory.CreateDirectory(coltFolderPath); - // While at that, start listening for colt/compile_errors.log changes - pathToLog = Path.Combine(coltFolderPath, "compile_errors.log"); - watcher.Path = coltFolderPath; - watcher.EnableRaisingEvents = true; + ConnectToCOLT(true); + - // Create COLT project with random name (if we'd update same file - are there file locks? how to reopen in colt?) + // Create COLT project with random name (todo: separate buttons for project export and project open) String coltFileName = project.GetAbsolutePath(Path.Combine(settingObject.WorkingFolder, System.Guid.NewGuid() + ".colt")); StreamWriter stream = File.CreateText(coltFileName); @@ -551,7 +568,7 @@ private void OpenInCOLT() } // Remove older *.colt files - foreach (String oldFile in Directory.GetFiles(coltFolderPath, "*.colt")) + foreach (String oldFile in Directory.GetFiles(project.GetAbsolutePath(settingObject.WorkingFolder), "*.colt")) { if (!coltFileName.Contains(Path.GetFileName(oldFile))) { diff --git a/ColtPlugin/Resources/en_US.resX b/ColtPlugin/Resources/en_US.resX index 9429a28..92f45f0 100644 --- a/ColtPlugin/Resources/en_US.resX +++ b/ColtPlugin/Resources/en_US.resX @@ -123,10 +123,4 @@ COLT Plugin for FlashDevelop. - - Do you want to overwrite COLT project to reflect new settings? - - - Project settings have changed - \ No newline at end of file diff --git a/ColtPlugin/Settings.cs b/ColtPlugin/Settings.cs index bce77e0..47090cd 100644 --- a/ColtPlugin/Settings.cs +++ b/ColtPlugin/Settings.cs @@ -11,7 +11,6 @@ public class Settings { private String workingFolder = "colt"; private Boolean fullConfig = false; - private Boolean alwaysOverwriteProjects = false; /// /// Get and sets colt folder @@ -35,17 +34,6 @@ public Boolean FullConfig set { this.fullConfig = value; } } - /// - /// Get and sets full config flag - /// - [DisplayName("Always overwrite COLT projects")] - [Description("Select this option to always overwrite COLT projects when FD project settings change."), DefaultValue(false)] - public Boolean AlwaysOverwriteProjects - { - get { return this.alwaysOverwriteProjects; } - set { this.alwaysOverwriteProjects = value; } - } - } } diff --git a/ColtPlugin/obj/Debug/ColtPlugin.dll b/ColtPlugin/obj/Debug/ColtPlugin.dll index 9cfa7faf99debcb267b56f28fda1da5a650eec48..401a6b2fbaee5eda7ce989dc4a810cfdc86620ba 100644 GIT binary patch delta 6953 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 Wr*D~U@QYs0whTE7j)}p^#(x7~j&Z;M delta 7626 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 BBGCW<